root/lm-sensors/trunk/kernel/chips/lm75.c @ 705

Revision 705, 11.6 KB (checked in by frodo, 14 years ago)

Removing kernel 2.0 and 2.1 compatibility pass 2

Eliminated compat.h

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    lm75.c - Part of lm_sensors, Linux kernel modules for hardware
3             monitoring
4    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21#include <linux/version.h>
22#include <linux/module.h>
23#include <linux/malloc.h>
24#include <linux/i2c.h>
25#include "sensors.h"
26#include "i2c-isa.h"
27#include "version.h"
28#include <linux/init.h>
29
30
31#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1))
32#define init_MUTEX(s) do { *(s) = MUTEX; } while(0)
33#endif
34
35#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13)
36#define THIS_MODULE NULL
37#endif
38
39/* Addresses to scan */
40static unsigned short normal_i2c[] = {SENSORS_I2C_END};
41static unsigned short normal_i2c_range[] = {0x48,0x4f,SENSORS_I2C_END};
42static unsigned int normal_isa[] = {SENSORS_ISA_END};
43static unsigned int normal_isa_range[] = {SENSORS_ISA_END};
44
45/* Insmod parameters */
46SENSORS_INSMOD_1(lm75);
47
48/* Many LM75 constants specified below */
49
50/* The LM75 registers */
51#define LM75_REG_TEMP 0x00
52#define LM75_REG_CONF 0x01
53#define LM75_REG_TEMP_HYST 0x02
54#define LM75_REG_TEMP_OS 0x03
55
56/* Conversions. Rounding and limit checking is only done on the TO_REG
57   variants. Note that you should be a bit careful with which arguments
58   these macros are called: arguments may be evaluated more than once.
59   Fixing this is just not worth it. */
60#define TEMP_FROM_REG(val) (((val) >> 7) * 5)
61#define TEMP_TO_REG(val)   (SENSORS_LIMIT(((((val) + 2) / 5) << 7),0,0xffff))
62
63/* Initial values */
64#define LM75_INIT_TEMP_OS 600
65#define LM75_INIT_TEMP_HYST 500
66
67/* Each client has this additional data */
68struct lm75_data {
69         int sysctl_id;
70
71         struct semaphore update_lock;
72         char valid;                 /* !=0 if following fields are valid */
73         unsigned long last_updated; /* In jiffies */
74
75         u16 temp,temp_os,temp_hyst; /* Register values */
76};
77
78#ifdef MODULE
79extern int init_module(void);
80extern int cleanup_module(void);
81#endif /* MODULE */
82
83#ifdef MODULE
84static
85#else
86extern
87#endif
88       int __init sensors_lm75_init(void);
89static int __init lm75_cleanup(void);
90static int lm75_attach_adapter(struct i2c_adapter *adapter);
91static int lm75_detect(struct i2c_adapter *adapter, int address, 
92                       unsigned short flags, int kind);
93static void lm75_init_client(struct i2c_client *client);
94static int lm75_detach_client(struct i2c_client *client);
95static int lm75_command(struct i2c_client *client, unsigned int cmd,
96                        void *arg);
97static void lm75_inc_use (struct i2c_client *client);
98static void lm75_dec_use (struct i2c_client *client);
99static u16 swap_bytes(u16 val);
100static int lm75_read_value(struct i2c_client *client, u8 reg);
101static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value);
102static void lm75_temp(struct i2c_client *client, int operation, int ctl_name,
103                      int *nrels_mag, long *results);
104static void lm75_update_client(struct i2c_client *client);
105
106
107/* This is the driver that will be inserted */
108static struct i2c_driver lm75_driver = {
109  /* name */            "LM75 sensor chip driver",
110  /* id */              I2C_DRIVERID_LM75,
111  /* flags */           I2C_DF_NOTIFY,
112  /* attach_adapter */  &lm75_attach_adapter,
113  /* detach_client */   &lm75_detach_client,
114  /* command */         &lm75_command,
115  /* inc_use */         &lm75_inc_use,
116  /* dec_use */         &lm75_dec_use
117};
118
119/* These files are created for each detected LM75. This is just a template;
120   though at first sight, you might think we could use a statically
121   allocated list, we need some way to get back to the parent - which
122   is done through one of the 'extra' fields which are initialized
123   when a new copy is allocated. */
124static ctl_table lm75_dir_table_template[] = {
125  { LM75_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &sensors_proc_real,
126    &sensors_sysctl_real, NULL, &lm75_temp },
127  { 0 }
128};
129
130/* Used by init/cleanup */
131static int __initdata lm75_initialized = 0;
132
133static int lm75_id = 0;
134
135int lm75_attach_adapter(struct i2c_adapter *adapter)
136{
137  return sensors_detect(adapter,&addr_data,lm75_detect);
138}
139
140/* This function is called by sensors_detect */
141int lm75_detect(struct i2c_adapter *adapter, int address, 
142                unsigned short flags, int kind)
143{
144  int i,cur,conf,hyst,os;
145  struct i2c_client *new_client;
146  struct lm75_data *data;
147  int err=0;
148  const char *type_name,*client_name;
149
150  /* Make sure we aren't probing the ISA bus!! This is just a safety check
151     at this moment; sensors_detect really won't call us. */
152#ifdef DEBUG
153  if (i2c_is_isa_adapter(adapter)) {
154    printk("lm75.o: lm75_detect called for an ISA bus adapter?!?\n");
155    return 0;
156  }
157#endif
158
159  if (! i2c_check_functionality(adapter,I2C_FUNC_SMBUS_BYTE_DATA |
160                                        I2C_FUNC_SMBUS_WORD_DATA))
161    goto ERROR0;
162
163  /* OK. For now, we presume we have a valid client. We now create the
164     client structure, even though we cannot fill it completely yet.
165     But it allows us to access lm75_{read,write}_value. */
166  if (! (new_client = kmalloc(sizeof(struct i2c_client) +
167                              sizeof(struct lm75_data),
168                              GFP_KERNEL))) {
169    err = -ENOMEM;
170    goto ERROR0;
171  }
172
173  data = (struct lm75_data *) (new_client + 1);
174  new_client->addr = address;
175  new_client->data = data;
176  new_client->adapter = adapter;
177  new_client->driver = &lm75_driver;
178  new_client->flags = 0;
179
180  /* Now, we do the remaining detection. It is lousy. */
181  if (kind < 0) {
182    cur = i2c_smbus_read_word_data(new_client,0);
183    conf = i2c_smbus_read_byte_data(new_client,1);
184    hyst = i2c_smbus_read_word_data(new_client,2);
185    os = i2c_smbus_read_word_data(new_client,3);
186    for (i = 0; i <= 0x1f; i++) 
187      if ((i2c_smbus_read_byte_data(new_client,i*8+1) != conf) ||
188          (i2c_smbus_read_word_data(new_client,i*8+2) != hyst) ||
189          (i2c_smbus_read_word_data(new_client,i*8+3) != os))
190        goto ERROR1;
191  }
192 
193  /* Determine the chip type - only one kind supported! */
194  if (kind <= 0)
195    kind = lm75;
196
197  if (kind == lm75) {
198    type_name = "lm75";
199    client_name = "LM75 chip";
200  } else {
201#ifdef DEBUG
202    printk("lm75.o: Internal error: unknown kind (%d)?!?",kind);
203#endif
204    goto ERROR1;
205  }
206 
207  /* Fill in the remaining client fields and put it into the global list */
208  strcpy(new_client->name,client_name);
209
210  new_client->id = lm75_id++;
211  data->valid = 0;
212  init_MUTEX(&data->update_lock);
213   
214  /* Tell the I2C layer a new client has arrived */
215  if ((err = i2c_attach_client(new_client)))
216    goto ERROR3;
217
218  /* Register a new directory entry with module sensors */
219  if ((i = sensors_register_entry(new_client,type_name,
220                                  lm75_dir_table_template,
221                                  THIS_MODULE)) < 0) {
222    err = i;
223    goto ERROR4;
224  }
225  data->sysctl_id = i;
226
227  lm75_init_client(new_client);
228  return 0;
229
230/* OK, this is not exactly good programming practice, usually. But it is
231   very code-efficient in this case. */
232
233ERROR4:
234  i2c_detach_client(new_client);
235ERROR3:
236ERROR1:
237  kfree(new_client);
238ERROR0:
239  return err;
240}
241
242int lm75_detach_client(struct i2c_client *client)
243{
244  int err;
245
246  sensors_deregister_entry(((struct lm75_data *)(client->data))->sysctl_id);
247
248  if ((err = i2c_detach_client(client))) {
249    printk("lm75.o: Client deregistration failed, client not detached.\n");
250    return err;
251  }
252
253  kfree(client);
254
255  return 0;
256}
257
258
259/* No commands defined yet */
260int lm75_command(struct i2c_client *client, unsigned int cmd, void *arg)
261{
262  return 0;
263}
264
265/* Nothing here yet */
266void lm75_inc_use (struct i2c_client *client)
267{
268#ifdef MODULE
269  MOD_INC_USE_COUNT;
270#endif
271}
272
273/* Nothing here yet */
274void lm75_dec_use (struct i2c_client *client)
275{
276#ifdef MODULE
277  MOD_DEC_USE_COUNT;
278#endif
279}
280
281u16 swap_bytes(u16 val)
282{
283  return (val >> 8) | (val << 8);
284}
285
286/* All registers are word-sized, except for the configuration register.
287   LM75 uses a high-byte first convention, which is exactly opposite to
288   the usual practice. */
289int lm75_read_value(struct i2c_client *client, u8 reg)
290{
291  if (reg == LM75_REG_CONF)
292    return i2c_smbus_read_byte_data(client,reg);
293  else
294    return swap_bytes(i2c_smbus_read_word_data(client,reg));
295}
296
297/* All registers are word-sized, except for the configuration register.
298   LM75 uses a high-byte first convention, which is exactly opposite to
299   the usual practice. */
300int lm75_write_value(struct i2c_client *client, u8 reg, u16 value)
301{
302  if (reg == LM75_REG_CONF)
303    return i2c_smbus_write_byte_data(client,reg,value);
304  else
305    return i2c_smbus_write_word_data(client,reg,
306           swap_bytes(value));
307}
308
309void lm75_init_client(struct i2c_client *client)
310{
311    /* Initialize the LM75 chip */
312    lm75_write_value(client,LM75_REG_TEMP_OS,
313                     TEMP_TO_REG(LM75_INIT_TEMP_OS));
314    lm75_write_value(client,LM75_REG_TEMP_HYST,
315                     TEMP_TO_REG(LM75_INIT_TEMP_HYST));
316    lm75_write_value(client,LM75_REG_CONF,0);
317}
318
319void lm75_update_client(struct i2c_client *client)
320{
321  struct lm75_data *data = client->data;
322
323  down(&data->update_lock);
324
325  if ((jiffies - data->last_updated > HZ+HZ/2 ) ||
326      (jiffies < data->last_updated) || ! data->valid) {
327
328#ifdef DEBUG
329    printk("Starting lm75 update\n");
330#endif
331
332    data->temp = lm75_read_value(client,LM75_REG_TEMP);
333    data->temp_os = lm75_read_value(client,LM75_REG_TEMP_OS);
334    data->temp_hyst = lm75_read_value(client,LM75_REG_TEMP_HYST);
335    data->last_updated = jiffies;
336    data->valid = 1;
337  }
338
339  up(&data->update_lock);
340}
341
342
343void lm75_temp(struct i2c_client *client, int operation, int ctl_name,
344               int *nrels_mag, long *results)
345{
346  struct lm75_data *data = client->data;
347  if (operation == SENSORS_PROC_REAL_INFO)
348    *nrels_mag = 1;
349  else if (operation == SENSORS_PROC_REAL_READ) {
350    lm75_update_client(client);
351    results[0] = TEMP_FROM_REG(data->temp_os);
352    results[1] = TEMP_FROM_REG(data->temp_hyst);
353    results[2] = TEMP_FROM_REG(data->temp);
354    *nrels_mag = 3;
355  } else if (operation == SENSORS_PROC_REAL_WRITE) {
356    if (*nrels_mag >= 1) {
357      data->temp_os = TEMP_TO_REG(results[0]);
358      lm75_write_value(client,LM75_REG_TEMP_OS,data->temp_os);
359    }
360    if (*nrels_mag >= 2) {
361      data->temp_hyst = TEMP_TO_REG(results[1]);
362      lm75_write_value(client,LM75_REG_TEMP_HYST,data->temp_hyst);
363    }
364  }
365}
366
367int __init sensors_lm75_init(void)
368{
369  int res;
370
371  printk("lm75.o version %s (%s)\n",LM_VERSION,LM_DATE);
372  lm75_initialized = 0;
373  if ((res = i2c_add_driver(&lm75_driver))) {
374    printk("lm75.o: Driver registration failed, module not inserted.\n");
375    lm75_cleanup();
376    return res;
377  }
378  lm75_initialized ++;
379  return 0;
380}
381
382int __init lm75_cleanup(void)
383{
384  int res;
385
386  if (lm75_initialized >= 1) {
387    if ((res = i2c_del_driver(&lm75_driver))) {
388      printk("lm75.o: Driver deregistration failed, module not removed.\n");
389      return res;
390    }
391    lm75_initialized --;
392  }
393
394  return 0;
395}
396
397EXPORT_NO_SYMBOLS;
398
399#ifdef MODULE
400
401MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
402MODULE_DESCRIPTION("LM75 driver");
403
404int init_module(void)
405{
406  return sensors_lm75_init();
407}
408
409int cleanup_module(void)
410{
411  return lm75_cleanup();
412}
413
414#endif /* MODULE */
415
Note: See TracBrowser for help on using the browser.