root/lm-sensors/trunk/kernel/chips/eeprom.c @ 467

Revision 467, 12.0 KB (checked in by frodo, 14 years ago)

Bradley M. Keryan's patches to make lm_sensors compile against
2.3.x kernels (x >= 1).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    eeprom.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/malloc.h>
24#include "smbus.h"
25#include "sensors.h"
26#include "i2c.h"
27#include "i2c-isa.h"
28#include "version.h"
29#include "compat.h"
30
31/* Addresses to scan */
32static unsigned short normal_i2c[] = {SENSORS_I2C_END};
33static unsigned short normal_i2c_range[] = {0x50,0x57,SENSORS_I2C_END};
34static unsigned int normal_isa[] = {SENSORS_ISA_END};
35static unsigned int normal_isa_range[] = {SENSORS_ISA_END};
36
37/* Insmod parameters */
38SENSORS_INSMOD_1(eeprom);
39
40static int checksum = 0;
41MODULE_PARM(checksum,"i");
42MODULE_PARM_DESC(checksum,"Only accept eeproms whose checksum is correct");
43
44
45/* Many constants specified below */
46
47/* EEPROM registers */
48#define EEPROM_REG_CHECKSUM 0x3f
49
50/* EEPROM memory types: */
51#define ONE_K           1
52#define TWO_K           2
53#define FOUR_K          3
54#define EIGHT_K         4
55#define SIXTEEN_K       5
56
57/* Conversions */
58/* Size of EEPROM in bytes */
59#define EEPROM_SIZE 128
60
61/* Each client has this additional data */
62struct eeprom_data {
63         int sysctl_id;
64
65         struct semaphore update_lock;
66         char valid;                 /* !=0 if following fields are valid */
67         unsigned long last_updated; /* In jiffies */
68
69         u8 data[EEPROM_SIZE]; /* Register values */
70         int memtype;
71};
72
73#ifdef MODULE
74extern int init_module(void);
75extern int cleanup_module(void);
76#endif /* MODULE */
77
78static int eeprom_init(void);
79static int eeprom_cleanup(void);
80
81static int eeprom_attach_adapter(struct i2c_adapter *adapter);
82static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind);
83static int eeprom_detach_client(struct i2c_client *client);
84static int eeprom_command(struct i2c_client *client, unsigned int cmd,
85                        void *arg);
86                       
87static void eeprom_inc_use (struct i2c_client *client);
88static void eeprom_dec_use (struct i2c_client *client);
89
90#if 0
91static int eeprom_write_value(struct i2c_client *client, u8 reg, u16 value);
92#endif
93
94static void eeprom_contents(struct i2c_client *client, int operation, int ctl_name,
95                      int *nrels_mag, long *results);
96static void eeprom_update_client(struct i2c_client *client);
97
98
99/* This is the driver that will be inserted */
100static struct i2c_driver eeprom_driver = {
101  /* name */            "EEPROM READER",
102  /* id */              I2C_DRIVERID_EEPROM,
103  /* flags */           DF_NOTIFY,
104  /* attach_adapter */  &eeprom_attach_adapter,
105  /* detach_client */   &eeprom_detach_client,
106  /* command */         &eeprom_command,
107  /* inc_use */         &eeprom_inc_use,
108  /* dec_use */         &eeprom_dec_use
109};
110
111/* These files are created for each detected EEPROM. This is just a template;
112   though at first sight, you might think we could use a statically
113   allocated list, we need some way to get back to the parent - which
114   is done through one of the 'extra' fields which are initialized
115   when a new copy is allocated. */
116static ctl_table eeprom_dir_table_template[] = {
117  { EEPROM_SYSCTL1, "data0-15", NULL, 0, 0444, NULL, &sensors_proc_real,
118    &sensors_sysctl_real, NULL, &eeprom_contents },
119  { EEPROM_SYSCTL2, "data16-31", NULL, 0, 0444, NULL, &sensors_proc_real,
120    &sensors_sysctl_real, NULL, &eeprom_contents },
121  { EEPROM_SYSCTL3, "data32-47", NULL, 0, 0444, NULL, &sensors_proc_real,
122    &sensors_sysctl_real, NULL, &eeprom_contents },
123  { EEPROM_SYSCTL4, "data48-63", NULL, 0, 0444, NULL, &sensors_proc_real,
124    &sensors_sysctl_real, NULL, &eeprom_contents },
125  { EEPROM_SYSCTL5, "data64-79", NULL, 0, 0444, NULL, &sensors_proc_real,
126    &sensors_sysctl_real, NULL, &eeprom_contents },
127  { EEPROM_SYSCTL6, "data80-95", NULL, 0, 0444, NULL, &sensors_proc_real,
128    &sensors_sysctl_real, NULL, &eeprom_contents },
129  { EEPROM_SYSCTL7, "data96-111", NULL, 0, 0444, NULL, &sensors_proc_real,
130    &sensors_sysctl_real, NULL, &eeprom_contents },
131  { EEPROM_SYSCTL8, "data112-127", NULL, 0, 0444, NULL, &sensors_proc_real,
132    &sensors_sysctl_real, NULL, &eeprom_contents },
133  { 0 }
134};
135
136/* Used by init/cleanup */
137static int eeprom_initialized = 0;
138
139/* I choose here for semi-static LM78 allocation. Complete dynamic
140   allocation could also be used; the code needed for this would probably
141   take more memory than the datastructure takes now. */
142#define MAX_EEPROM_NR 8
143static struct i2c_client *eeprom_list[MAX_EEPROM_NR];
144
145int eeprom_attach_adapter(struct i2c_adapter *adapter)
146{
147  return sensors_detect(adapter,&addr_data,eeprom_detect);
148}
149
150/* This function is called by sensors_detect */
151int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
152{
153  int i,cs;
154  struct i2c_client *new_client;
155  struct eeprom_data *data;
156  int err=0;
157  const char *type_name,*client_name;
158
159  /* Make sure we aren't probing the ISA bus!! This is just a safety check
160     at this moment; sensors_detect really won't call us. */
161#ifdef DEBUG
162  if (i2c_is_isa_adapter(adapter)) {
163    printk("eeprom.o: eeprom_detect called for an ISA bus adapter?!?\n");
164    return 0;
165  }
166#endif
167
168  /* Here, we have to do the address registration check for the I2C bus.
169     But that is not yet implemented. */
170
171  /* OK. For now, we presume we have a valid client. We now create the
172     client structure, even though we cannot fill it completely yet.
173     But it allows us to access eeprom_{read,write}_value. */
174  if (! (new_client = kmalloc(sizeof(struct i2c_client) +
175                              sizeof(struct eeprom_data),
176                              GFP_KERNEL))) {
177    err = -ENOMEM;
178    goto ERROR0;
179  }
180
181  data = (struct eeprom_data *) (((struct i2c_client *) new_client) + 1);
182  new_client->addr = address;
183  new_client->data = data;
184  new_client->adapter = adapter;
185  new_client->driver = &eeprom_driver;
186
187  /* Now, we do the remaining detection. It is not there, unless you force
188     the checksum to work out. */
189  if (checksum) {
190    cs = 0;
191    for (i = 0; i <= 0x3e; i++)
192      cs += smbus_read_byte_data(adapter,address,i);
193    cs &= 0xff;
194    if (smbus_read_byte_data(adapter,address,EEPROM_REG_CHECKSUM) != cs)
195      goto ERROR1;
196  }
197 
198  /* Determine the chip type - only one kind supported! */
199  if (kind <= 0)
200    kind = eeprom;
201
202  if (kind == eeprom) {
203    type_name = "eeprom";
204    client_name = "EEPROM chip";
205  } else {
206#ifdef DEBUG
207    printk("eeprom.o: Internal error: unknown kind (%d)?!?",kind);
208#endif
209    goto ERROR1;
210  }
211
212  /* Fill in the remaining client fields and put it into the global list */
213  strcpy(new_client->name,client_name);
214
215  /* Find a place in our global list */
216  for (i = 0; i < MAX_EEPROM_NR; i++)
217    if (! eeprom_list[i])
218       break;
219  if (i == MAX_EEPROM_NR) {
220    err = -ENOMEM;
221    printk("eeprom.o: No empty slots left, recompile and heighten "
222           "MAX_EEPROM_NR!\n");
223    goto ERROR2;
224  }
225  eeprom_list[i] = new_client;
226  new_client->id = i;
227  data->valid = 0;
228  init_MUTEX(&data->update_lock);
229
230  /* Tell the I2C layer a new client has arrived */
231  if ((err = i2c_attach_client(new_client)))
232    goto ERROR3;
233
234  /* Register a new directory entry with module sensors */
235  if ((i = sensors_register_entry(new_client,type_name,
236                                  eeprom_dir_table_template)) < 0) {
237    err = i;
238    goto ERROR4;
239  }
240  data->sysctl_id = i;
241
242  return 0;
243
244/* OK, this is not exactly good programming practice, usually. But it is
245   very code-efficient in this case. */
246
247ERROR4:
248  i2c_detach_client(new_client);
249ERROR3:
250  for (i = 0; i < MAX_EEPROM_NR; i++)
251    if (new_client == eeprom_list[i])
252      eeprom_list[i] = NULL;
253ERROR2:
254ERROR1:
255  kfree(new_client);
256ERROR0:
257  return err;
258}
259
260int eeprom_detach_client(struct i2c_client *client)
261{
262  int err,i;
263
264  sensors_deregister_entry(((struct eeprom_data *)(client->data))->sysctl_id);
265
266  if ((err = i2c_detach_client(client))) {
267    printk("eeprom.o: Client deregistration failed, client not detached.\n");
268    return err;
269  }
270
271  for (i = 0; i < MAX_EEPROM_NR; i++)
272    if (client == eeprom_list[i])
273      break;
274  if ((i == MAX_EEPROM_NR)) {
275    printk("eeprom.o: Client to detach not found.\n");
276    return -ENOENT;
277  }
278  eeprom_list[i] = NULL;
279
280  kfree(client);
281
282  return 0;
283}
284
285
286/* No commands defined yet */
287int eeprom_command(struct i2c_client *client, unsigned int cmd, void *arg)
288{
289  return 0;
290}
291
292void eeprom_inc_use (struct i2c_client *client)
293{
294#ifdef MODULE
295  MOD_INC_USE_COUNT;
296#endif
297}
298
299void eeprom_dec_use (struct i2c_client *client)
300{
301#ifdef MODULE
302  MOD_DEC_USE_COUNT;
303#endif
304}
305
306#if 0
307/* No writes yet (PAE) */
308int eeprom_write_value(struct i2c_client *client, u8 reg, u16 value)
309{
310  if (reg == EEPROM_REG_CONF)
311    return smbus_write_byte_data(client->adapter,client->addr,reg,value);
312  else
313    return smbus_write_word_data(client->adapter,client->addr,reg,value); */
314   
315    return 0;
316}
317#endif
318
319void eeprom_update_client(struct i2c_client *client)
320{
321  struct eeprom_data *data = client->data;
322  int i;
323
324  down(&data->update_lock);
325
326  if ((jiffies - data->last_updated > HZ+HZ/2 ) ||
327      (jiffies < data->last_updated) || ! data->valid) {
328
329#ifdef DEBUG
330    printk("Starting eeprom update\n");
331#endif
332
333   if (smbus_write_byte(client->adapter,client->addr,0)) {
334#ifdef DEBUG
335    printk("eeprom read start has failed!\n");
336#endif         
337   }
338    for (i=0;i<EEPROM_SIZE;i++) {
339         data->data[i] = (u8)smbus_read_byte(client->adapter,client->addr);
340    }
341   
342    data->last_updated = jiffies;
343    data->valid = 1;
344  }
345
346  up(&data->update_lock);
347}
348
349
350void eeprom_contents(struct i2c_client *client, int operation, int ctl_name,
351               int *nrels_mag, long *results)
352{
353  int i;
354  int base=0;
355  struct eeprom_data *data = client->data;
356 
357  if (ctl_name == EEPROM_SYSCTL2){ base=16; }
358  if (ctl_name == EEPROM_SYSCTL3){ base=32; }
359  if (ctl_name == EEPROM_SYSCTL4){ base=48; }
360  if (ctl_name == EEPROM_SYSCTL5){ base=64; }
361  if (ctl_name == EEPROM_SYSCTL6){ base=80; }
362  if (ctl_name == EEPROM_SYSCTL7){ base=96; }
363  if (ctl_name == EEPROM_SYSCTL8){ base=112; }
364 
365  if (operation == SENSORS_PROC_REAL_INFO)
366    *nrels_mag = 0;
367  else if (operation == SENSORS_PROC_REAL_READ) {
368    eeprom_update_client(client);
369    for (i=0; i<16; i++) {
370        results[i]=data->data[i + base];
371    }
372#ifdef DEBUG
373    printk("eeprom.o: 0x%X EEPROM Contents (base %d): ",client->addr,base);
374    for (i=0; i<16; i++) {
375      printk(" 0x%X",data->data[i + base]);
376    }
377    printk(" .\n");
378#endif
379    *nrels_mag = 16;
380  } else if (operation == SENSORS_PROC_REAL_WRITE) {
381
382/* No writes to the EEPROM (yet, anyway) (PAE) */
383        printk("eeprom.o: No writes to EEPROMs supported!\n");
384  }
385}
386
387int eeprom_init(void)
388{
389  int res;
390
391  printk("eeprom.o version %s (%s)\n",LM_VERSION,LM_DATE);
392  eeprom_initialized = 0;
393  if ((res = i2c_add_driver(&eeprom_driver))) {
394    printk("eeprom.o: Driver registration failed, module not inserted.\n");
395    eeprom_cleanup();
396    return res;
397  }
398  eeprom_initialized ++;
399  return 0;
400}
401
402int eeprom_cleanup(void)
403{
404  int res;
405
406  if (eeprom_initialized >= 1) {
407    if ((res = i2c_del_driver(&eeprom_driver))) {
408      printk("eeprom.o: Driver deregistration failed, module not removed.\n");
409      return res;
410    }
411  } else
412    eeprom_initialized --;
413
414  return 0;
415}
416
417
418#ifdef MODULE
419
420MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
421MODULE_DESCRIPTION("EEPROM driver");
422
423int init_module(void)
424{
425  return eeprom_init();
426}
427
428int cleanup_module(void)
429{
430  return eeprom_cleanup();
431}
432
433#endif /* MODULE */
434
Note: See TracBrowser for help on using the browser.