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

Revision 704, 16.8 KB (checked in by frodo, 13 years ago)

Removal of kernel 2.1 and 2.2 compatibility: pass one

Removed many #if statements

  • 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/malloc.h>
25#include <linux/i2c.h>
26#include "sensors.h"
27#include "i2c-isa.h"
28#include "version.h"
29#include "compat.h"
30
31#include <linux/init.h>
32
33/* Addresses to scan */
34static unsigned short normal_i2c[] = {SENSORS_I2C_END};
35static unsigned short normal_i2c_range[] = {0x18,0x1a,0x29,0x2b,
36                                            0x4c,0x4e,SENSORS_I2C_END};
37static unsigned int normal_isa[] = {SENSORS_ISA_END};
38static unsigned int normal_isa_range[] = {SENSORS_ISA_END};
39
40/* Insmod parameters */
41SENSORS_INSMOD_6(adm1021,max1617,max1617a,thmc10,lm84,gl523sm);
42
43/* adm1021 constants specified below */
44
45/* The adm1021 registers */
46/* Read-only */
47#define ADM1021_REG_TEMP 0x00
48#define ADM1021_REG_REMOTE_TEMP 0x01
49#define ADM1021_REG_STATUS 0x02
50#define ADM1021_REG_MAN_ID 0x0FE  /* 0x41 = AMD, 0x49 = TI, 0x4D = Maxim, 0x23 = Genesys */
51#define ADM1021_REG_DEV_ID 0x0FF /* ADM1021 */
52#define ADM1021_REG_DIE_CODE 0x0FF /* MAX1617A */
53/* These use different addresses for reading/writing */
54#define ADM1021_REG_CONFIG_R 0x03
55#define ADM1021_REG_CONFIG_W 0x09
56#define ADM1021_REG_CONV_RATE_R 0x04
57#define ADM1021_REG_CONV_RATE_W 0x0A
58#define ADM1021_REG_TOS_R 0x05
59#define ADM1021_REG_TOS_W 0x0B
60#define ADM1021_REG_REMOTE_TOS_R 0x07
61#define ADM1021_REG_REMOTE_TOS_W 0x0D
62#define ADM1021_REG_THYST_R 0x06
63#define ADM1021_REG_THYST_W 0x0C
64#define ADM1021_REG_REMOTE_THYST_R 0x08
65#define ADM1021_REG_REMOTE_THYST_W 0x0E
66/* write-only */
67#define ADM1021_REG_ONESHOT 0x0F
68
69
70/* Conversions. Rounding and limit checking is only done on the TO_REG
71   variants. Note that you should be a bit careful with which arguments
72   these macros are called: arguments may be evaluated more than once.
73   Fixing this is just not worth it. */
74/* Conversions  note: 1021 uses normal integer signed-byte format*/
75#define TEMP_FROM_REG(val) (val > 127 ? val-256 : val)
76#define TEMP_TO_REG(val)   (SENSORS_LIMIT((val < 0 ? val+256 : val),0,255))
77
78/* Initial values */
79
80/* Note: Eventhough I left the low and high limits named os and hyst,
81they don't quite work like a thermostat the way the LM75 does.  I.e.,
82a lower temp than THYST actuall triggers an alarm instead of
83clearing it.  Weird, ey?   --Phil  */
84#define adm1021_INIT_TOS 60
85#define adm1021_INIT_THYST 20
86#define adm1021_INIT_REMOTE_TOS 60
87#define adm1021_INIT_REMOTE_THYST 20
88
89/* Each client has this additional data */
90struct adm1021_data {
91         int sysctl_id;
92         enum chips type;
93
94         struct semaphore update_lock;
95         char valid;                 /* !=0 if following fields are valid */
96         unsigned long last_updated; /* In jiffies */
97
98         u8 temp,temp_os,temp_hyst; /* Register values */
99         u8 remote_temp,remote_temp_os,remote_temp_hyst,alarms,die_code; 
100};
101
102#ifdef MODULE
103extern int init_module(void);
104extern int cleanup_module(void);
105#endif /* MODULE */
106
107#ifdef MODULE
108static
109#else
110extern
111#endif
112       int __init sensors_adm1021_init(void);
113static int __init adm1021_cleanup(void);
114static int adm1021_attach_adapter(struct i2c_adapter *adapter);
115static int adm1021_detect(struct i2c_adapter *adapter, int address, 
116                          unsigned short flags, int kind);
117static void adm1021_init_client(struct i2c_client *client);
118static int adm1021_detach_client(struct i2c_client *client);
119static int adm1021_command(struct i2c_client *client, unsigned int cmd,
120                        void *arg);
121static void adm1021_inc_use (struct i2c_client *client);
122static void adm1021_dec_use (struct i2c_client *client);
123static int adm1021_read_value(struct i2c_client *client, u8 reg);
124static int adm1021_write_value(struct i2c_client *client, u8 reg, u16 value);
125static void adm1021_temp(struct i2c_client *client, int operation, int ctl_name,
126                      int *nrels_mag, long *results);
127static void adm1021_remote_temp(struct i2c_client *client, int operation, int ctl_name,
128                      int *nrels_mag, long *results);
129static void adm1021_alarms(struct i2c_client *client, int operation, int ctl_name,
130                      int *nrels_mag, long *results);
131static void adm1021_die_code(struct i2c_client *client, int operation, int ctl_name,
132                      int *nrels_mag, long *results);
133static void adm1021_update_client(struct i2c_client *client);
134
135
136/* This is the driver that will be inserted */
137static struct i2c_driver adm1021_driver = {
138  /* name */            "ADM1021, MAX1617 sensor driver",
139  /* id */              I2C_DRIVERID_ADM1021,
140  /* flags */           I2C_DF_NOTIFY,
141  /* attach_adapter */  &adm1021_attach_adapter,
142  /* detach_client */   &adm1021_detach_client,
143  /* command */         &adm1021_command,
144  /* inc_use */         &adm1021_inc_use,
145  /* dec_use */         &adm1021_dec_use
146};
147
148/* These files are created for each detected adm1021. This is just a template;
149   though at first sight, you might think we could use a statically
150   allocated list, we need some way to get back to the parent - which
151   is done through one of the 'extra' fields which are initialized
152   when a new copy is allocated. */
153static ctl_table adm1021_dir_table_template[] = {
154  { ADM1021_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &sensors_proc_real,
155    &sensors_sysctl_real, NULL, &adm1021_temp },
156    {ADM1021_SYSCTL_REMOTE_TEMP, "remote_temp", NULL, 0, 0644, NULL, &sensors_proc_real,
157    &sensors_sysctl_real, NULL, &adm1021_remote_temp },
158    {ADM1021_SYSCTL_DIE_CODE, "die_code", NULL, 0, 0444, NULL, &sensors_proc_real,
159    &sensors_sysctl_real, NULL, &adm1021_die_code },
160    {ADM1021_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &sensors_proc_real,
161    &sensors_sysctl_real, NULL, &adm1021_alarms },
162  { 0 }
163};
164
165static ctl_table adm1021_max_dir_table_template[] = {
166  { ADM1021_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &sensors_proc_real,
167    &sensors_sysctl_real, NULL, &adm1021_temp },
168    {ADM1021_SYSCTL_REMOTE_TEMP, "remote_temp", NULL, 0, 0644, NULL, &sensors_proc_real,
169    &sensors_sysctl_real, NULL, &adm1021_remote_temp },
170    {ADM1021_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &sensors_proc_real,
171    &sensors_sysctl_real, NULL, &adm1021_alarms },
172  { 0 }
173};
174
175
176/* Used by init/cleanup */
177static int __initdata adm1021_initialized = 0;
178
179/* I choose here for semi-static allocation. Complete dynamic
180   allocation could also be used; the code needed for this would probably
181   take more memory than the datastructure takes now. */
182static int adm1021_id = 0;
183
184int adm1021_attach_adapter(struct i2c_adapter *adapter)
185{
186  return sensors_detect(adapter,&addr_data,adm1021_detect);
187}
188
189static int adm1021_detect(struct i2c_adapter *adapter, int address, 
190                          unsigned short flags, int kind)
191{ 
192  int i;
193  struct i2c_client *new_client;
194  struct adm1021_data *data;
195  int err=0;
196  const char *type_name = "";
197  const char *client_name = "";
198
199  /* Make sure we aren't probing the ISA bus!! This is just a safety check
200     at this moment; sensors_detect really won't call us. */
201#ifdef DEBUG
202  if (i2c_is_isa_adapter(adapter)) {
203    printk("adm1021.o: adm1021_detect called for an ISA bus adapter?!?\n");
204    return 0;
205  }
206#endif
207
208  if (! i2c_check_functionality(adapter,I2C_FUNC_SMBUS_BYTE_DATA))
209    goto ERROR0;
210
211  /* OK. For now, we presume we have a valid client. We now create the
212     client structure, even though we cannot fill it completely yet.
213     But it allows us to access adm1021_{read,write}_value. */
214
215  if (! (new_client = kmalloc(sizeof(struct i2c_client) +
216                               sizeof(struct adm1021_data),
217                               GFP_KERNEL))) {
218    err = -ENOMEM;
219    goto ERROR0;
220  }
221
222  data = (struct adm1021_data *) (new_client + 1);
223  new_client->addr = address;
224  new_client->data = data;
225  new_client->adapter = adapter;
226  new_client->driver = &adm1021_driver;
227  new_client->flags = 0;
228
229  /* Now, we do the remaining detection. */
230
231  if (kind < 0) {
232    if ((adm1021_read_value(new_client,ADM1021_REG_STATUS) & 0x03) != 0x00)
233      goto ERROR1;
234  }
235
236  /* Determine the chip type. */
237 
238  if (kind <= 0) {
239    i = adm1021_read_value(new_client,ADM1021_REG_MAN_ID);
240    if (i == 0x41)
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(new_client,ADM1021_REG_DEV_ID) == 0x01))
248      kind = max1617a;
249    /* LM84 Mfr ID in a different place */
250    else if (adm1021_read_value(new_client,ADM1021_REG_CONV_RATE_R) == 0x00)
251      kind = lm84;
252    else 
253      kind = max1617;
254  }
255
256  if (kind == max1617) {
257    type_name = "max1617";
258    client_name = "MAX1617 chip";
259  } else if (kind == max1617a) {
260    type_name = "max1617a";
261    client_name = "MAX1617A chip";
262  } else if (kind == adm1021) {
263    type_name = "adm1021";
264    client_name = "ADM1021 chip";
265  } else if (kind == thmc10) {
266    type_name = "thmc10";
267    client_name = "THMC10 chip";
268  } else {
269#ifdef DEBUG
270    printk("adm1021.o: Internal error: unknown kind (%d)?!?",kind);
271#endif
272    goto ERROR1;
273  }
274
275  /* Fill in the remaining client fields and put it into the global list */
276  strcpy(new_client->name,client_name);
277  data->type = kind;
278
279  new_client->id = adm1021_id++;
280  data->valid = 0;
281  init_MUTEX(&data->update_lock);
282
283  /* Tell the I2C layer a new client has arrived */
284  if ((err = i2c_attach_client(new_client)))
285    goto ERROR3;
286
287  /* Register a new directory entry with module sensors */
288  if ((i = sensors_register_entry(new_client,
289                        type_name,
290                        data->type==adm1021?adm1021_dir_table_template:
291                                    adm1021_max_dir_table_template,
292                        THIS_MODULE)) < 0) {
293    err = i;
294    goto ERROR4;
295  }
296  data->sysctl_id = i;
297
298  /* Initialize the ADM1021 chip */
299  adm1021_init_client(new_client);
300  return 0;
301
302/* OK, this is not exactly good programming practice, usually. But it is
303   very code-efficient in this case. */
304
305ERROR4:
306  i2c_detach_client(new_client);
307ERROR3:
308ERROR1:
309  kfree(new_client);
310ERROR0:
311  return err;
312}
313
314void adm1021_init_client(struct i2c_client *client)
315{
316  /* Initialize the adm1021 chip */
317  adm1021_write_value(client,ADM1021_REG_TOS_W,
318                   TEMP_TO_REG(adm1021_INIT_TOS));
319  adm1021_write_value(client,ADM1021_REG_THYST_W,
320                   TEMP_TO_REG(adm1021_INIT_THYST));
321  adm1021_write_value(client,ADM1021_REG_REMOTE_TOS_W,
322                   TEMP_TO_REG(adm1021_INIT_REMOTE_TOS));
323  adm1021_write_value(client,ADM1021_REG_REMOTE_THYST_W,
324                   TEMP_TO_REG(adm1021_INIT_REMOTE_THYST));
325  /* Enable ADC and disable suspend mode */
326  adm1021_write_value(client,ADM1021_REG_CONFIG_W,0); 
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
331int adm1021_detach_client(struct i2c_client *client)
332{
333
334  int err;
335
336  sensors_deregister_entry(((struct adm1021_data *)(client->data))->sysctl_id);
337
338  if ((err = i2c_detach_client(client))) {
339    printk("adm1021.o: Client deregistration failed, client not detached.\n");
340    return err;
341  }
342
343  kfree(client);
344
345  return 0;
346
347}
348
349
350/* No commands defined yet */
351int adm1021_command(struct i2c_client *client, unsigned int cmd, void *arg)
352{
353  return 0;
354}
355
356void adm1021_inc_use (struct i2c_client *client)
357{
358#ifdef MODULE
359  MOD_INC_USE_COUNT;
360#endif
361}
362
363void adm1021_dec_use (struct i2c_client *client)
364{
365#ifdef MODULE
366  MOD_DEC_USE_COUNT;
367#endif
368}
369
370/* All registers are byte-sized */
371int adm1021_read_value(struct i2c_client *client, u8 reg)
372{
373    return i2c_smbus_read_byte_data(client,reg);
374}
375
376int adm1021_write_value(struct i2c_client *client, u8 reg, u16 value)
377{
378    return i2c_smbus_write_byte_data(client,reg,value);
379}
380
381void adm1021_update_client(struct i2c_client *client)
382{
383  struct adm1021_data *data = client->data;
384
385  down(&data->update_lock);
386
387  if ((jiffies - data->last_updated > HZ+HZ/2 ) ||
388      (jiffies < data->last_updated) || ! data->valid) {
389
390#ifdef DEBUG
391    printk("Starting adm1021 update\n");
392#endif
393
394    data->temp = adm1021_read_value(client,ADM1021_REG_TEMP);
395    data->temp_os = adm1021_read_value(client,ADM1021_REG_TOS_R);
396    data->temp_hyst = adm1021_read_value(client,ADM1021_REG_THYST_R);
397    data->remote_temp = adm1021_read_value(client,ADM1021_REG_REMOTE_TEMP);
398    data->remote_temp_os = adm1021_read_value(client,ADM1021_REG_REMOTE_TOS_R);
399    data->remote_temp_hyst = adm1021_read_value(client,ADM1021_REG_REMOTE_THYST_R);
400    data->alarms = adm1021_read_value(client,ADM1021_REG_STATUS) & 0xec;
401    if (data->type == adm1021)
402      data->die_code = adm1021_read_value(client,ADM1021_REG_DIE_CODE);
403    data->last_updated = jiffies;
404    data->valid = 1;
405  }
406
407  up(&data->update_lock);
408}
409
410
411void adm1021_temp(struct i2c_client *client, int operation, int ctl_name,
412               int *nrels_mag, long *results)
413{
414  struct adm1021_data *data = client->data;
415  if (operation == SENSORS_PROC_REAL_INFO)
416    *nrels_mag = 0;
417  else if (operation == SENSORS_PROC_REAL_READ) {
418    adm1021_update_client(client);
419    results[0] = TEMP_FROM_REG(data->temp_os);
420    results[1] = TEMP_FROM_REG(data->temp_hyst);
421    results[2] = TEMP_FROM_REG(data->temp);
422    *nrels_mag = 3;
423  } else if (operation == SENSORS_PROC_REAL_WRITE) {
424    if (*nrels_mag >= 1) {
425      data->temp_os = TEMP_TO_REG(results[0]);
426      adm1021_write_value(client,ADM1021_REG_TOS_W,data->temp_os);
427    }
428    if (*nrels_mag >= 2) {
429      data->temp_hyst = TEMP_TO_REG(results[1]);
430      adm1021_write_value(client,ADM1021_REG_THYST_W,data->temp_hyst);
431    }
432  }
433}
434
435void adm1021_remote_temp(struct i2c_client *client, int operation, int ctl_name,
436               int *nrels_mag, long *results)
437{
438  struct adm1021_data *data = client->data;
439  if (operation == SENSORS_PROC_REAL_INFO)
440    *nrels_mag = 0;
441  else if (operation == SENSORS_PROC_REAL_READ) {
442    adm1021_update_client(client);
443    results[0] = TEMP_FROM_REG(data->remote_temp_os);
444    results[1] = TEMP_FROM_REG(data->remote_temp_hyst);
445    results[2] = TEMP_FROM_REG(data->remote_temp);
446    *nrels_mag = 3;
447  } else if (operation == SENSORS_PROC_REAL_WRITE) {
448    if (*nrels_mag >= 1) {
449      data->remote_temp_os = TEMP_TO_REG(results[0]);
450      adm1021_write_value(client,ADM1021_REG_REMOTE_TOS_W,data->remote_temp_os);
451    }
452    if (*nrels_mag >= 2) {
453      data->remote_temp_hyst = TEMP_TO_REG(results[1]);
454      adm1021_write_value(client,ADM1021_REG_REMOTE_THYST_W,data->remote_temp_hyst);
455    }
456  }
457}
458
459void adm1021_die_code(struct i2c_client *client, int operation, int ctl_name,
460               int *nrels_mag, long *results)
461{
462  struct adm1021_data *data = client->data;
463  if (operation == SENSORS_PROC_REAL_INFO)
464    *nrels_mag = 0;
465  else if (operation == SENSORS_PROC_REAL_READ) {
466    adm1021_update_client(client);
467    results[0] = data->die_code;
468    *nrels_mag = 1;
469  } else if (operation == SENSORS_PROC_REAL_WRITE) {
470    /* Can't write to it */
471  }
472}
473
474void adm1021_alarms(struct i2c_client *client, int operation, int ctl_name,
475               int *nrels_mag, long *results)
476{
477  struct adm1021_data *data = client->data;
478  if (operation == SENSORS_PROC_REAL_INFO)
479    *nrels_mag = 0;
480  else if (operation == SENSORS_PROC_REAL_READ) {
481    adm1021_update_client(client);
482    results[0] = data->alarms;
483    *nrels_mag = 1;
484  } else if (operation == SENSORS_PROC_REAL_WRITE) {
485    /* Can't write to it */
486  }
487}
488
489int __init sensors_adm1021_init(void)
490{
491  int res;
492
493  printk("adm1021.o version %s (%s)\n",LM_VERSION,LM_DATE);
494  adm1021_initialized = 0;
495  if ((res = i2c_add_driver(&adm1021_driver))) {
496    printk("adm1021.o: Driver registration failed, module not inserted.\n");
497    adm1021_cleanup();
498    return res;
499  }
500  adm1021_initialized ++;
501  return 0;
502}
503
504int __init adm1021_cleanup(void)
505{
506  int res;
507
508  if (adm1021_initialized >= 1) {
509    if ((res = i2c_del_driver(&adm1021_driver))) {
510      printk("adm1021.o: Driver deregistration failed, module not removed.\n");
511      return res;
512    }
513    adm1021_initialized --;
514  }
515
516  return 0;
517}
518
519EXPORT_NO_SYMBOLS;
520
521#ifdef MODULE
522
523MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
524MODULE_DESCRIPTION("adm1021 driver");
525
526int init_module(void)
527{
528  return sensors_adm1021_init();
529}
530
531int cleanup_module(void)
532{
533  return adm1021_cleanup();
534}
535
536#endif /* MODULE */
537
Note: See TracBrowser for help on using the browser.