root/lm-sensors/trunk/kernel/chips/adm1021.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    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/module.h>
23#include <linux/slab.h>
24#include <linux/i2c.h>
25#include <linux/i2c-proc.h>
26#include <linux/init.h>
27#include "version.h"
28
29/* Addresses to scan */
30static unsigned short normal_i2c[] = { SENSORS_I2C_END };
31static unsigned short normal_i2c_range[] = { 0x18, 0x1a, 0x29, 0x2b,
32        0x4c, 0x4e, SENSORS_I2C_END
33};
34static unsigned int normal_isa[] = { SENSORS_ISA_END };
35static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
36
37/* Insmod parameters */
38SENSORS_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, mc1066);
39
40/* adm1021 constants specified below */
41
42/* The adm1021 registers */
43/* Read-only */
44#define ADM1021_REG_TEMP 0x00
45#define ADM1021_REG_REMOTE_TEMP 0x01
46#define ADM1021_REG_STATUS 0x02
47#define ADM1021_REG_MAN_ID 0x0FE        /* 0x41 = Analog Devices, 0x49 = TI,
48                                       0x4D = Maxim, 0x23 = Genesys , 0x54 = Onsemi*/
49#define ADM1021_REG_DEV_ID 0x0FF        /* ADM1021 = 0x0X, ADM1021A/ADM1023 = 0x3X */
50#define ADM1021_REG_DIE_CODE 0x0FF      /* MAX1617A */
51/* These use different addresses for reading/writing */
52#define ADM1021_REG_CONFIG_R 0x03
53#define ADM1021_REG_CONFIG_W 0x09
54#define ADM1021_REG_CONV_RATE_R 0x04
55#define ADM1021_REG_CONV_RATE_W 0x0A
56/* These are for the ADM1023's additional precision on the remote temp sensor */
57#define ADM1021_REG_REM_TEMP_PREC 0x010
58#define ADM1021_REG_REM_OFFSET 0x011
59#define ADM1021_REG_REM_OFFSET_PREC 0x012
60#define ADM1021_REG_REM_TOS_PREC 0x013
61#define ADM1021_REG_REM_THYST_PREC 0x014
62/* limits */
63#define ADM1021_REG_TOS_R 0x05
64#define ADM1021_REG_TOS_W 0x0B
65#define ADM1021_REG_REMOTE_TOS_R 0x07
66#define ADM1021_REG_REMOTE_TOS_W 0x0D
67#define ADM1021_REG_THYST_R 0x06
68#define ADM1021_REG_THYST_W 0x0C
69#define ADM1021_REG_REMOTE_THYST_R 0x08
70#define ADM1021_REG_REMOTE_THYST_W 0x0E
71/* write-only */
72#define ADM1021_REG_ONESHOT 0x0F
73
74#define ADM1021_ALARM_TEMP (ADM1021_ALARM_TEMP_HIGH | ADM1021_ALARM_TEMP_LOW)
75#define ADM1021_ALARM_RTEMP (ADM1021_ALARM_RTEMP_HIGH | ADM1021_ALARM_RTEMP_LOW\
76                             | ADM1021_ALARM_RTEMP_NA)
77#define ADM1021_ALARM_ALL  (ADM1021_ALARM_TEMP | ADM1021_ALARM_RTEMP)
78
79/* Conversions. Rounding and limit checking is only done on the TO_REG
80   variants. Note that you should be a bit careful with which arguments
81   these macros are called: arguments may be evaluated more than once.
82   Fixing this is just not worth it. */
83/* Conversions  note: 1021 uses normal integer signed-byte format*/
84#define TEMP_FROM_REG(val) (val > 127 ? val-256 : val)
85#define TEMP_TO_REG(val)   (SENSORS_LIMIT((val < 0 ? val+256 : val),0,255))
86
87/* Each client has this additional data */
88struct adm1021_data {
89        struct i2c_client client;
90        int sysctl_id;
91        enum chips type;
92
93        struct semaphore update_lock;
94        char valid;             /* !=0 if following fields are valid */
95        unsigned long last_updated;     /* In jiffies */
96
97        u8 temp, temp_os, temp_hyst;    /* Register values */
98        u8 remote_temp, remote_temp_os, remote_temp_hyst, alarms, die_code;
99        u8 fail;
100        /* Special values for ADM1023 only */
101        u8 remote_temp_prec, remote_temp_os_prec, remote_temp_hyst_prec, 
102           remote_temp_offset, remote_temp_offset_prec;
103};
104
105static int adm1021_attach_adapter(struct i2c_adapter *adapter);
106static int adm1021_detect(struct i2c_adapter *adapter, int address,
107                          unsigned short flags, int kind);
108static void adm1021_init_client(struct i2c_client *client);
109static int adm1021_detach_client(struct i2c_client *client);
110static int adm1021_read_value(struct i2c_client *client, u8 reg);
111static int adm1021_rd_good(u8 *val, struct i2c_client *client, u8 reg, u8 mask);
112static int adm1021_write_value(struct i2c_client *client, u8 reg,
113                               u16 value);
114static void adm1021_temp(struct i2c_client *client, int operation,
115                         int ctl_name, int *nrels_mag, long *results);
116static void adm1021_remote_temp(struct i2c_client *client, int operation,
117                                int ctl_name, int *nrels_mag,
118                                long *results);
119static void adm1021_alarms(struct i2c_client *client, int operation,
120                           int ctl_name, int *nrels_mag, long *results);
121static void adm1021_die_code(struct i2c_client *client, int operation,
122                             int ctl_name, int *nrels_mag, long *results);
123static void adm1021_update_client(struct i2c_client *client);
124
125/* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */
126static int read_only = 0;
127
128
129/* This is the driver that will be inserted */
130static struct i2c_driver adm1021_driver = {
131        .name           = "ADM1021, MAX1617 sensor driver",
132        .id             = I2C_DRIVERID_ADM1021,
133        .flags          = I2C_DF_NOTIFY,
134        .attach_adapter = adm1021_attach_adapter,
135        .detach_client  = adm1021_detach_client,
136};
137
138/* -- SENSORS SYSCTL START -- */
139
140#define ADM1021_SYSCTL_TEMP 1200
141#define ADM1021_SYSCTL_REMOTE_TEMP 1201
142#define ADM1021_SYSCTL_DIE_CODE 1202
143#define ADM1021_SYSCTL_ALARMS 1203
144
145#define ADM1021_ALARM_TEMP_HIGH 0x40
146#define ADM1021_ALARM_TEMP_LOW 0x20
147#define ADM1021_ALARM_RTEMP_HIGH 0x10
148#define ADM1021_ALARM_RTEMP_LOW 0x08
149#define ADM1021_ALARM_RTEMP_NA 0x04
150
151/* -- SENSORS SYSCTL END -- */
152
153/* These files are created for each detected adm1021. This is just a template;
154   though at first sight, you might think we could use a statically
155   allocated list, we need some way to get back to the parent - which
156   is done through one of the 'extra' fields which are initialized
157   when a new copy is allocated. */
158static ctl_table adm1021_dir_table_template[] = {
159        {ADM1021_SYSCTL_TEMP, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
160         &i2c_sysctl_real, NULL, &adm1021_temp},
161        {ADM1021_SYSCTL_REMOTE_TEMP, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
162         &i2c_sysctl_real, NULL, &adm1021_remote_temp},
163        {ADM1021_SYSCTL_DIE_CODE, "die_code", NULL, 0, 0444, NULL, &i2c_proc_real,
164         &i2c_sysctl_real, NULL, &adm1021_die_code},
165        {ADM1021_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
166         &i2c_sysctl_real, NULL, &adm1021_alarms},
167        {0}
168};
169
170static ctl_table adm1021_max_dir_table_template[] = {
171        {ADM1021_SYSCTL_TEMP, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
172         &i2c_sysctl_real, NULL, &adm1021_temp},
173        {ADM1021_SYSCTL_REMOTE_TEMP, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
174         &i2c_sysctl_real, NULL, &adm1021_remote_temp},
175        {ADM1021_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
176         &i2c_sysctl_real, NULL, &adm1021_alarms},
177        {0}
178};
179
180static int adm1021_attach_adapter(struct i2c_adapter *adapter)
181{
182        return i2c_detect(adapter, &addr_data, adm1021_detect);
183}
184
185static int adm1021_detect(struct i2c_adapter *adapter, int address,
186                          unsigned short flags, int kind)
187{
188        int i;
189        struct i2c_client *new_client;
190        struct adm1021_data *data;
191        int err = 0;
192        const char *type_name = "";
193        const char *client_name = "";
194
195        /* Make sure we aren't probing the ISA bus!! This is just a safety check
196           at this moment; i2c_detect really won't call us. */
197#ifdef DEBUG
198        if (i2c_is_isa_adapter(adapter)) {
199                printk
200                    ("adm1021.o: adm1021_detect called for an ISA bus adapter?!?\n");
201                return 0;
202        }
203#endif
204
205        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
206                goto error0;
207
208        /* OK. For now, we presume we have a valid client. We now create the
209           client structure, even though we cannot fill it completely yet.
210           But it allows us to access adm1021_{read,write}_value. */
211
212        if (!(data = kmalloc(sizeof(struct adm1021_data), GFP_KERNEL))) {
213                err = -ENOMEM;
214                goto error0;
215        }
216
217        new_client = &data->client;
218        new_client->addr = address;
219        new_client->data = data;
220        new_client->adapter = adapter;
221        new_client->driver = &adm1021_driver;
222        new_client->flags = 0;
223
224        /* Now, we do the remaining detection. */
225
226        if (kind < 0) {
227                if ((adm1021_read_value(new_client, ADM1021_REG_STATUS) & 0x03) != 0x00
228                 || (adm1021_read_value(new_client, ADM1021_REG_CONFIG_R) & 0x3F) != 0x00
229                 || (adm1021_read_value(new_client, ADM1021_REG_CONV_RATE_R) & 0xF8) != 0x00)
230                        goto error1;
231        }
232
233        /* Determine the chip type. */
234
235        if (kind <= 0) {
236                i = adm1021_read_value(new_client, ADM1021_REG_MAN_ID);
237                if (i == 0x41)
238                  if ((adm1021_read_value (new_client, ADM1021_REG_DEV_ID) & 0xF0) == 0x30)
239                        kind = adm1023;
240                  else
241                        kind = adm1021;
242                else if (i == 0x49)
243                        kind = thmc10;
244                else if (i == 0x23)
245                        kind = gl523sm;
246                else if ((i == 0x4d) &&
247                         (adm1021_read_value
248                          (new_client, ADM1021_REG_DEV_ID) == 0x01))
249                        kind = max1617a;
250                else if (i == 0x54)
251                        kind = mc1066;
252                /* LM84 Mfr ID in a different place, and it has more unused bits */
253                else if (adm1021_read_value(new_client, ADM1021_REG_CONV_RATE_R) == 0x00
254                      && (kind == 0 /* skip extra detection */
255                       || ((adm1021_read_value(new_client, ADM1021_REG_CONFIG_R) & 0x7F) == 0x00
256                        && (adm1021_read_value(new_client, ADM1021_REG_STATUS) & 0xAB) == 0x00)))
257                        kind = lm84;
258                else
259                        kind = max1617;
260        }
261
262        if (kind == max1617) {
263                type_name = "max1617";
264                client_name = "MAX1617 chip";
265        } else if (kind == max1617a) {
266                type_name = "max1617a";
267                client_name = "MAX1617A chip";
268        } else if (kind == adm1021) {
269                type_name = "adm1021";
270                client_name = "ADM1021 chip";
271        } else if (kind == adm1023) {
272                type_name = "adm1023";
273                client_name = "ADM1023 chip";
274        } else if (kind == thmc10) {
275                type_name = "thmc10";
276                client_name = "THMC10 chip";
277        } else if (kind == lm84) {
278                type_name = "lm84";
279                client_name = "LM84 chip";
280        } else if (kind == gl523sm) {
281                type_name = "gl523sm";
282                client_name = "GL523SM chip";
283        } else if (kind == mc1066) {
284                type_name = "mc1066";
285                client_name = "MC1066 chip";
286        }
287
288        /* Fill in the remaining client fields and put it into the global list */
289        strcpy(new_client->name, client_name);
290        data->type = kind;
291        data->valid = 0;
292        init_MUTEX(&data->update_lock);
293
294        /* Tell the I2C layer a new client has arrived */
295        if ((err = i2c_attach_client(new_client)))
296                goto error3;
297
298        /* Register a new directory entry with module sensors */
299        if ((i = i2c_register_entry(new_client, type_name,
300                                        data->type == adm1021 ? adm1021_dir_table_template :
301                                        adm1021_max_dir_table_template,
302                                        THIS_MODULE)) < 0) {
303                err = i;
304                goto error4;
305        }
306        data->sysctl_id = i;
307
308        /* Initialize the ADM1021 chip */
309        if (kind != lm84)
310                adm1021_init_client(new_client);
311        return 0;
312
313      error4:
314        i2c_detach_client(new_client);
315      error3:
316      error1:
317        kfree(data);
318      error0:
319        return err;
320}
321
322static void adm1021_init_client(struct i2c_client *client)
323{
324        /* Enable ADC and disable suspend mode */
325        adm1021_write_value(client, ADM1021_REG_CONFIG_W,
326                adm1021_read_value(client, ADM1021_REG_CONFIG_R) & 0xBF);
327        /* Set Conversion rate to 1/sec (this can be tinkered with) */
328        adm1021_write_value(client, ADM1021_REG_CONV_RATE_W, 0x04);
329}
330
331static int adm1021_detach_client(struct i2c_client *client)
332{
333        int err;
334
335        i2c_deregister_entry(((struct adm1021_data *) (client->data))->
336                                 sysctl_id);
337
338        if ((err = i2c_detach_client(client))) {
339                printk
340                    ("adm1021.o: Client deregistration failed, client not detached.\n");
341                return err;
342        }
343
344        kfree(client->data);
345
346        return 0;
347}
348
349
350/* All registers are byte-sized */
351static int adm1021_read_value(struct i2c_client *client, u8 reg)
352{
353        return i2c_smbus_read_byte_data(client, reg);
354}
355
356/* only update value if read succeeded; set fail bit if failed */
357static int adm1021_rd_good(u8 *val, struct i2c_client *client, u8 reg, u8 mask)
358{
359        int i;
360        struct adm1021_data *data = client->data;
361
362        i = i2c_smbus_read_byte_data(client, reg);
363        if (i < 0) {
364                data->fail |= mask;
365                return i;
366        }
367        *val = i;
368        return 0;
369}
370
371static int adm1021_write_value(struct i2c_client *client, u8 reg, u16 value)
372{
373        if (read_only > 0)
374                return 0;
375
376        return i2c_smbus_write_byte_data(client, reg, value);
377}
378
379static void adm1021_update_client(struct i2c_client *client)
380{
381        struct adm1021_data *data = client->data;
382
383        down(&data->update_lock);
384
385        if ((jiffies - data->last_updated > HZ + HZ / 2) ||
386            (jiffies < data->last_updated) || !data->valid) {
387
388#ifdef DEBUG
389                printk("Starting adm1021 update\n");
390#endif
391
392                data->fail = 0;
393                adm1021_rd_good(&(data->temp), client, ADM1021_REG_TEMP,
394                                ADM1021_ALARM_TEMP);
395                adm1021_rd_good(&(data->temp_os), client, ADM1021_REG_TOS_R,
396                                ADM1021_ALARM_TEMP);
397                adm1021_rd_good(&(data->temp_hyst), client,
398                                ADM1021_REG_THYST_R, ADM1021_ALARM_TEMP);
399                adm1021_rd_good(&(data->remote_temp), client,
400                                ADM1021_REG_REMOTE_TEMP, ADM1021_ALARM_RTEMP);
401                adm1021_rd_good(&(data->remote_temp_os), client,
402                                ADM1021_REG_REMOTE_TOS_R, ADM1021_ALARM_RTEMP);
403                adm1021_rd_good(&(data->remote_temp_hyst), client,
404                                ADM1021_REG_REMOTE_THYST_R,
405                                ADM1021_ALARM_RTEMP);
406                data->alarms = ADM1021_ALARM_ALL;
407                if (!adm1021_rd_good(&(data->alarms), client,
408                                     ADM1021_REG_STATUS, 0))
409                        data->alarms &= ADM1021_ALARM_ALL;
410                if (data->type == adm1021)
411                        adm1021_rd_good(&(data->die_code), client,
412                                        ADM1021_REG_DIE_CODE, 0);
413                if (data->type == adm1023) {
414                        adm1021_rd_good(&(data->remote_temp_prec), client,
415                                        ADM1021_REG_REM_TEMP_PREC,
416                                        ADM1021_ALARM_TEMP);
417                        adm1021_rd_good(&(data->remote_temp_os_prec), client,
418                                        ADM1021_REG_REM_TOS_PREC,
419                                        ADM1021_ALARM_RTEMP);
420                        adm1021_rd_good(&(data->remote_temp_hyst_prec), client,
421                                        ADM1021_REG_REM_THYST_PREC,
422                                        ADM1021_ALARM_RTEMP);
423                        adm1021_rd_good(&(data->remote_temp_offset), client,
424                                        ADM1021_REG_REM_OFFSET,
425                                        ADM1021_ALARM_RTEMP);
426                        adm1021_rd_good(&(data->remote_temp_offset_prec),
427                                        client, ADM1021_REG_REM_OFFSET_PREC,
428                                        ADM1021_ALARM_RTEMP);
429                }
430                data->last_updated = jiffies;
431                data->valid = 1;
432        }
433
434        up(&data->update_lock);
435}
436
437
438void adm1021_temp(struct i2c_client *client, int operation, int ctl_name,
439                  int *nrels_mag, long *results)
440{
441        struct adm1021_data *data = client->data;
442        if (operation == SENSORS_PROC_REAL_INFO)
443                *nrels_mag = 0;
444        else if (operation == SENSORS_PROC_REAL_READ) {
445                adm1021_update_client(client);
446                results[0] = TEMP_FROM_REG(data->temp_os);
447                results[1] = TEMP_FROM_REG(data->temp_hyst);
448                results[2] = TEMP_FROM_REG(data->temp);
449                *nrels_mag = 3;
450        } else if (operation == SENSORS_PROC_REAL_WRITE) {
451                if (*nrels_mag >= 1) {
452                        data->temp_os = TEMP_TO_REG(results[0]);
453                        adm1021_write_value(client, ADM1021_REG_TOS_W,
454                                            data->temp_os);
455                }
456                if (*nrels_mag >= 2) {
457                        data->temp_hyst = TEMP_TO_REG(results[1]);
458                        adm1021_write_value(client, ADM1021_REG_THYST_W,
459                                            data->temp_hyst);
460                }
461        }
462}
463
464void adm1021_remote_temp(struct i2c_client *client, int operation,
465                         int ctl_name, int *nrels_mag, long *results)
466{
467        struct adm1021_data *data = client->data;
468        int prec = 0;
469
470        if (operation == SENSORS_PROC_REAL_INFO)
471                if (data->type == adm1023) { *nrels_mag = 3; }
472                 else { *nrels_mag = 0; }
473        else if (operation == SENSORS_PROC_REAL_READ) {
474                adm1021_update_client(client);
475                results[0] = TEMP_FROM_REG(data->remote_temp_os);
476                results[1] = TEMP_FROM_REG(data->remote_temp_hyst);
477                results[2] = TEMP_FROM_REG(data->remote_temp);
478                if (data->type == adm1023) {
479                  results[0]=results[0]*1000 + 
480                   ((data->remote_temp_os_prec >> 5) * 125);
481                  results[1]=results[1]*1000 + 
482                   ((data->remote_temp_hyst_prec >> 5) * 125);
483                  results[2]=(TEMP_FROM_REG(data->remote_temp_offset)*1000) + 
484                   ((data->remote_temp_offset_prec >> 5) * 125);
485                  results[3]=TEMP_FROM_REG(data->remote_temp)*1000 + 
486                   ((data->remote_temp_prec >> 5) * 125);
487                  *nrels_mag = 4;
488                } else {
489                  *nrels_mag = 3;
490                }
491        } else if (operation == SENSORS_PROC_REAL_WRITE) {
492                if (*nrels_mag >= 1) {
493                        if (data->type == adm1023) {
494                          prec=((results[0]-((results[0]/1000)*1000))/125)<<5;
495                          adm1021_write_value(client,
496                                            ADM1021_REG_REM_TOS_PREC,
497                                            prec);
498                          results[0]=results[0]/1000;
499                          data->remote_temp_os_prec=prec;
500                        }
501                        data->remote_temp_os = TEMP_TO_REG(results[0]);
502                        adm1021_write_value(client,
503                                            ADM1021_REG_REMOTE_TOS_W,
504                                            data->remote_temp_os);
505                }
506                if (*nrels_mag >= 2) {
507                        if (data->type == adm1023) {
508                          prec=((results[1]-((results[1]/1000)*1000))/125)<<5;
509                          adm1021_write_value(client,
510                                            ADM1021_REG_REM_THYST_PREC,
511                                            prec);
512                          results[1]=results[1]/1000;
513                          data->remote_temp_hyst_prec=prec;
514                        }
515                        data->remote_temp_hyst = TEMP_TO_REG(results[1]);
516                        adm1021_write_value(client,
517                                            ADM1021_REG_REMOTE_THYST_W,
518                                            data->remote_temp_hyst);
519                }
520                if (*nrels_mag >= 3) {
521                        if (data->type == adm1023) {
522                          prec=((results[2]-((results[2]/1000)*1000))/125)<<5;
523                          adm1021_write_value(client,
524                                            ADM1021_REG_REM_OFFSET_PREC,
525                                            prec);
526                          results[2]=results[2]/1000;
527                          data->remote_temp_offset_prec=prec;
528                          data->remote_temp_offset=results[2];
529                          adm1021_write_value(client,
530                                            ADM1021_REG_REM_OFFSET,
531                                            data->remote_temp_offset);
532                        }
533                }
534        }
535}
536
537void adm1021_die_code(struct i2c_client *client, int operation,
538                      int ctl_name, int *nrels_mag, long *results)
539{
540        struct adm1021_data *data = client->data;
541        if (operation == SENSORS_PROC_REAL_INFO)
542                *nrels_mag = 0;
543        else if (operation == SENSORS_PROC_REAL_READ) {
544                adm1021_update_client(client);
545                results[0] = data->die_code;
546                *nrels_mag = 1;
547        } else if (operation == SENSORS_PROC_REAL_WRITE) {
548                /* Can't write to it */
549        }
550}
551
552void adm1021_alarms(struct i2c_client *client, int operation, int ctl_name,
553                    int *nrels_mag, long *results)
554{
555        struct adm1021_data *data = client->data;
556        if (operation == SENSORS_PROC_REAL_INFO)
557                *nrels_mag = 0;
558        else if (operation == SENSORS_PROC_REAL_READ) {
559                adm1021_update_client(client);
560                results[0] = data->alarms | data->fail;
561                *nrels_mag = 1;
562        } else if (operation == SENSORS_PROC_REAL_WRITE) {
563                /* Can't write to it */
564        }
565}
566
567static int __init sm_adm1021_init(void)
568{
569        printk(KERN_INFO "adm1021.o version %s (%s)\n", LM_VERSION, LM_DATE);
570        return i2c_add_driver(&adm1021_driver);
571}
572
573static void __exit sm_adm1021_exit(void)
574{
575        i2c_del_driver(&adm1021_driver);
576}
577
578MODULE_AUTHOR
579    ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
580MODULE_DESCRIPTION("adm1021 driver");
581MODULE_LICENSE("GPL");
582
583MODULE_PARM(read_only, "i");
584MODULE_PARM_DESC(read_only, "Don't set any values, read only mode");
585
586module_init(sm_adm1021_init)
587module_exit(sm_adm1021_exit)
Note: See TracBrowser for help on using the browser.