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

Revision 4652, 10.5 KB (checked in by khali, 7 years ago)

Delete dead code.

  • 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    2003-08-18  Jean Delvare <khali@linux-fr.org>
8    Divide the eeprom in 2-row (arbitrary) slices. This significantly
9    speeds sensors up, as well as various scripts using the eeprom
10    module.
11
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 2 of the License, or
15    (at your option) any later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software
24    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25*/
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 <linux/sched.h> /* for capable() */
33#include "version.h"
34
35MODULE_LICENSE("GPL");
36
37/* Addresses to scan */
38static unsigned short normal_i2c[] = { SENSORS_I2C_END };
39static unsigned short normal_i2c_range[] = { 0x50, 0x57, 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_1(eeprom);
45
46
47/* possible natures */
48#define NATURE_UNKNOWN 0
49#define NATURE_VAIO 1
50
51/* Size of EEPROM in bytes */
52#define EEPROM_SIZE 256
53
54/* Each client has this additional data */
55struct eeprom_data {
56        struct i2c_client client;
57        int sysctl_id;
58
59        struct semaphore update_lock;
60        u8 valid;               /* bitfield, bit!=0 if slice is valid */
61        unsigned long last_updated[8];  /* In jiffies, 8 slices */
62
63        u8 data[EEPROM_SIZE];   /* Register values */
64        u8 nature;
65};
66
67
68static int eeprom_attach_adapter(struct i2c_adapter *adapter);
69static int eeprom_detect(struct i2c_adapter *adapter, int address,
70                         unsigned short flags, int kind);
71static int eeprom_detach_client(struct i2c_client *client);
72
73static void eeprom_contents(struct i2c_client *client, int operation,
74                            int ctl_name, int *nrels_mag, long *results);
75static void eeprom_update_client(struct i2c_client *client, u8 slice);
76
77
78/* This is the driver that will be inserted */
79static struct i2c_driver eeprom_driver = {
80        .name           = "EEPROM READER",
81        .id             = I2C_DRIVERID_EEPROM,
82        .flags          = I2C_DF_NOTIFY,
83        .attach_adapter = eeprom_attach_adapter,
84        .detach_client  = eeprom_detach_client,
85};
86
87/* -- SENSORS SYSCTL START -- */
88
89#define EEPROM_SYSCTL1 1000
90#define EEPROM_SYSCTL2 1001
91#define EEPROM_SYSCTL3 1002
92#define EEPROM_SYSCTL4 1003
93#define EEPROM_SYSCTL5 1004
94#define EEPROM_SYSCTL6 1005
95#define EEPROM_SYSCTL7 1006
96#define EEPROM_SYSCTL8 1007
97#define EEPROM_SYSCTL9 1008
98#define EEPROM_SYSCTL10 1009
99#define EEPROM_SYSCTL11 1010
100#define EEPROM_SYSCTL12 1011
101#define EEPROM_SYSCTL13 1012
102#define EEPROM_SYSCTL14 1013
103#define EEPROM_SYSCTL15 1014
104#define EEPROM_SYSCTL16 1015
105
106/* -- SENSORS SYSCTL END -- */
107
108/* These files are created for each detected EEPROM. This is just a template;
109   though at first sight, you might think we could use a statically
110   allocated list, we need some way to get back to the parent - which
111   is done through one of the 'extra' fields which are initialized
112   when a new copy is allocated. */
113static ctl_table eeprom_dir_table_template[] = {
114        {EEPROM_SYSCTL1, "00", NULL, 0, 0444, NULL, &i2c_proc_real,
115         &i2c_sysctl_real, NULL, &eeprom_contents},
116        {EEPROM_SYSCTL2, "10", NULL, 0, 0444, NULL, &i2c_proc_real,
117         &i2c_sysctl_real, NULL, &eeprom_contents},
118        {EEPROM_SYSCTL3, "20", NULL, 0, 0444, NULL, &i2c_proc_real,
119         &i2c_sysctl_real, NULL, &eeprom_contents},
120        {EEPROM_SYSCTL4, "30", NULL, 0, 0444, NULL, &i2c_proc_real,
121         &i2c_sysctl_real, NULL, &eeprom_contents},
122        {EEPROM_SYSCTL5, "40", NULL, 0, 0444, NULL, &i2c_proc_real,
123         &i2c_sysctl_real, NULL, &eeprom_contents},
124        {EEPROM_SYSCTL6, "50", NULL, 0, 0444, NULL, &i2c_proc_real,
125         &i2c_sysctl_real, NULL, &eeprom_contents},
126        {EEPROM_SYSCTL7, "60", NULL, 0, 0444, NULL, &i2c_proc_real,
127         &i2c_sysctl_real, NULL, &eeprom_contents},
128        {EEPROM_SYSCTL8, "70", NULL, 0, 0444, NULL, &i2c_proc_real,
129         &i2c_sysctl_real, NULL, &eeprom_contents},
130        {EEPROM_SYSCTL9, "80", NULL, 0, 0444, NULL, &i2c_proc_real,
131         &i2c_sysctl_real, NULL, &eeprom_contents},
132        {EEPROM_SYSCTL10, "90", NULL, 0, 0444, NULL, &i2c_proc_real,
133         &i2c_sysctl_real, NULL, &eeprom_contents},
134        {EEPROM_SYSCTL11, "a0", NULL, 0, 0444, NULL, &i2c_proc_real,
135         &i2c_sysctl_real, NULL, &eeprom_contents},
136        {EEPROM_SYSCTL12, "b0", NULL, 0, 0444, NULL, &i2c_proc_real,
137         &i2c_sysctl_real, NULL, &eeprom_contents},
138        {EEPROM_SYSCTL13, "c0", NULL, 0, 0444, NULL, &i2c_proc_real,
139         &i2c_sysctl_real, NULL, &eeprom_contents},
140        {EEPROM_SYSCTL14, "d0", NULL, 0, 0444, NULL, &i2c_proc_real,
141         &i2c_sysctl_real, NULL, &eeprom_contents},
142        {EEPROM_SYSCTL15, "e0", NULL, 0, 0444, NULL, &i2c_proc_real,
143         &i2c_sysctl_real, NULL, &eeprom_contents},
144        {EEPROM_SYSCTL16, "f0", NULL, 0, 0444, NULL, &i2c_proc_real,
145         &i2c_sysctl_real, NULL, &eeprom_contents},
146        {0}
147};
148
149static int eeprom_attach_adapter(struct i2c_adapter *adapter)
150{
151        return i2c_detect(adapter, &addr_data, eeprom_detect);
152}
153
154/* This function is called by i2c_detect */
155static int eeprom_detect(struct i2c_adapter *adapter, int address,
156                         unsigned short flags, int kind)
157{
158        int i;
159        struct i2c_client *new_client;
160        struct eeprom_data *data;
161        int err = 0;
162        const char *type_name;
163
164        /* There are three ways we can read the EEPROM data:
165           (1) I2C block reads (faster, but unsupported by most adapters)
166           (2) Consecutive byte reads (100% overhead)
167           (3) Regular byte data reads (200% overhead)
168           The third method is not implemented by this driver because all
169           known adapters support at least the second. */
170        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA
171                                            | I2C_FUNC_SMBUS_BYTE))
172                goto ERROR0;
173
174        if (!(data = kmalloc(sizeof(struct eeprom_data), GFP_KERNEL))) {
175                err = -ENOMEM;
176                goto ERROR0;
177        }
178
179        new_client = &data->client;
180        memset(data->data, 0xff, EEPROM_SIZE);
181        new_client->addr = address;
182        new_client->data = data;
183        new_client->adapter = adapter;
184        new_client->driver = &eeprom_driver;
185        new_client->flags = 0;
186
187        /* prevent 24RF08 corruption */
188        i2c_smbus_write_quick(new_client, 0);
189
190        type_name = "eeprom";
191
192        /* Fill in the remaining client fields and put it into the global list */
193        strcpy(new_client->name, "EEPROM chip");
194        data->valid = 0;
195        init_MUTEX(&data->update_lock);
196        data->nature = NATURE_UNKNOWN;
197
198        /* Tell the I2C layer a new client has arrived */
199        if ((err = i2c_attach_client(new_client)))
200                goto ERROR3;
201
202        /* Detect the Vaio nature of EEPROMs.
203           We use the "PCG-" prefix as the signature. */
204        if (address == 0x57) {
205                if (i2c_smbus_read_byte_data(new_client, 0x80) == 'P'
206                 && i2c_smbus_read_byte(new_client) == 'C'
207                 && i2c_smbus_read_byte(new_client) == 'G'
208                 && i2c_smbus_read_byte(new_client) == '-') {
209                        printk(KERN_INFO "Vaio EEPROM detected, "
210                               "enabling password protection\n");
211                        data->nature = NATURE_VAIO;
212                }
213        }
214
215        /* Register a new directory entry with module sensors */
216        if ((i = i2c_register_entry(new_client, type_name,
217                                        eeprom_dir_table_template,
218                                        THIS_MODULE)) < 0) {
219                err = i;
220                goto ERROR4;
221        }
222        data->sysctl_id = i;
223
224        return 0;
225
226      ERROR4:
227        i2c_detach_client(new_client);
228      ERROR3:
229        kfree(data);
230      ERROR0:
231        return err;
232}
233
234static int eeprom_detach_client(struct i2c_client *client)
235{
236        int err;
237
238        i2c_deregister_entry(((struct eeprom_data *) (client->data))->
239                                 sysctl_id);
240
241        if ((err = i2c_detach_client(client))) {
242                printk
243                    ("eeprom.o: Client deregistration failed, client not detached.\n");
244                return err;
245        }
246
247        kfree(client->data);
248
249        return 0;
250}
251
252static void eeprom_update_client(struct i2c_client *client, u8 slice)
253{
254        struct eeprom_data *data = client->data;
255        int i, j;
256
257        down(&data->update_lock);
258
259        if (!(data->valid & (1 << slice))
260         || (jiffies - data->last_updated[slice] > 300 * HZ)
261         || (jiffies < data->last_updated[slice])) {
262
263#ifdef DEBUG
264                printk(KERN_DEBUG "eeprom.o: Starting update, slice %u\n", slice);
265#endif
266
267                if (i2c_check_functionality(client->adapter,
268                                            I2C_FUNC_SMBUS_READ_I2C_BLOCK))
269                {
270                        for (i = slice << 5; i < (slice + 1) << 5;
271                                                    i += I2C_SMBUS_I2C_BLOCK_MAX)
272                                if (i2c_smbus_read_i2c_block_data(client,
273                                                           i, data->data + i)
274                                                    != I2C_SMBUS_I2C_BLOCK_MAX) {
275                                        printk(KERN_WARNING "eeprom.o: block read fail at 0x%.2x!\n", i);
276                                        goto DONE;
277                                }
278                } else {
279                        if (i2c_smbus_write_byte(client, slice << 5)) {
280                                printk(KERN_WARNING "eeprom.o: read start fail at 0x%.2x!\n", slice << 5);
281                                goto DONE;
282                        }
283                        for (i = slice << 5; i < (slice + 1) << 5; i++) {
284                                j = i2c_smbus_read_byte(client);
285                                if (j < 0) {
286                                        printk(KERN_WARNING "eeprom.o: read fail at 0x%.2x!\n", i);
287                                        goto DONE;
288                                }
289                                data->data[i] = (u8) j;
290                        }
291                }
292                data->last_updated[slice] = jiffies;
293                data->valid |= (1 << slice);
294        }
295DONE:
296        up(&data->update_lock);
297}
298
299
300void eeprom_contents(struct i2c_client *client, int operation,
301                     int ctl_name, int *nrels_mag, long *results)
302{
303        int i;
304        int nr = ctl_name - EEPROM_SYSCTL1;
305        struct eeprom_data *data = client->data;
306
307        if (operation == SENSORS_PROC_REAL_INFO)
308                *nrels_mag = 0;
309        else if (operation == SENSORS_PROC_REAL_READ) {
310                eeprom_update_client(client, nr >> 1);
311                /* Hide Vaio security settings to regular users */
312                if (nr == 0 && data->nature == NATURE_VAIO
313                 && !capable(CAP_SYS_ADMIN))
314                        for (i = 0; i < 16; i++)
315                                results[i] = 0;
316                else
317                        for (i = 0; i < 16; i++)
318                                results[i] = data->data[i + nr * 16];
319#ifdef DEBUG
320                printk(KERN_DEBUG "eeprom.o: 0x%X EEPROM contents (row %d):",
321                       client->addr, nr + 1);
322                if (nr == 0 && data->nature == NATURE_VAIO)
323                        printk(" <hidden for security reasons>\n");
324                else {
325                        for (i = 0; i < 16; i++)
326                                printk(" 0x%02X", data->data[i + nr * 16]);
327                        printk("\n");
328                }
329#endif
330                *nrels_mag = 16;
331        }
332}
333
334static int __init sm_eeprom_init(void)
335{
336        printk("eeprom.o version %s (%s)\n", LM_VERSION, LM_DATE);
337        return i2c_add_driver(&eeprom_driver);
338}
339
340static void __exit sm_eeprom_exit(void)
341{
342        i2c_del_driver(&eeprom_driver);
343}
344
345
346
347MODULE_AUTHOR
348    ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
349MODULE_DESCRIPTION("EEPROM driver");
350
351module_init(sm_eeprom_init);
352module_exit(sm_eeprom_exit);
Note: See TracBrowser for help on using the browser.