root/lm-sensors/trunk/kernel/chips/smartbatt.c @ 2784

Revision 2784, 16.9 KB (checked in by khali, 8 years ago)

Restore controlling_mod argument to i2c_register_entry(). This
is needed to properly lock chip drivers in memory while anyone uses their
/proc entries. This also brings back compatibility with the 2.4 Linux
kernel.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    smartbatt.c - Part of lm_sensors, Linux kernel modules for hardware
3             monitoring
4    Copyright (c) 2002  M. D. Studebaker <mdsxyz123@yahoo.com>
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    With GPL code from:
21           battery.c
22           Copyright (C) 2000 Linuxcare, Inc.
23           battery.h
24           Copyright (C) 2000 Hypercore Software Design, Ltd.
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 "version.h"
33
34
35/* Addresses to scan */
36static unsigned short normal_i2c[] = { SENSORS_I2C_END };
37static unsigned short normal_i2c_range[] = { 0x0b, SENSORS_I2C_END };
38static unsigned int normal_isa[] = { SENSORS_ISA_END };
39static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
40
41/* Insmod parameters */
42SENSORS_INSMOD_1(smartbatt);
43
44/* The SMARTBATT registers */
45#define SMARTBATT_REG_MODE 0x03
46#define SMARTBATT_REG_TEMP 0x08
47#define SMARTBATT_REG_V 0x09
48#define SMARTBATT_REG_I 0x0a
49#define SMARTBATT_REG_AVGI 0x0b
50#define SMARTBATT_REG_RELCHG 0x0d
51#define SMARTBATT_REG_ABSCHG 0x0e
52#define SMARTBATT_REG_REMCAP 0x0f
53#define SMARTBATT_REG_CHGCAP 0x10
54#define SMARTBATT_REG_RUNTIME_E 0x11
55#define SMARTBATT_REG_AVGTIME_E 0x12
56#define SMARTBATT_REG_AVGTIME_F 0x13
57#define SMARTBATT_REG_CHGI 0x14
58#define SMARTBATT_REG_CHGV 0x15
59#define SMARTBATT_REG_STATUS 0x16
60#define SMARTBATT_REG_CYCLECT 0x17
61#define SMARTBATT_REG_DESCAP 0x18
62#define SMARTBATT_REG_DESV 0x19
63#define SMARTBATT_REG_DATE 0x1b
64#define SMARTBATT_REG_SERIAL 0x1c
65#define SMARTBATT_REG_MANUF 0x20
66#define SMARTBATT_REG_NAME 0x21
67#define SMARTBATT_REG_CHEM 0x22
68
69#define BATTERY_STRING_MAX      64
70#define COMM_TIMEOUT 16
71
72
73/* Each client has this additional data */
74struct smartbatt_data {
75        struct i2c_client client;
76        int sysctl_id;
77
78        struct semaphore update_lock;
79        char valid;             /* !=0 if following fields are valid */
80        unsigned long last_updated;     /* In jiffies */
81#if 0
82        char manufacturer[BATTERY_STRING_MAX];
83        char device[BATTERY_STRING_MAX];
84        char chemistry[BATTERY_STRING_MAX];
85#endif
86        int  serial;
87        struct {
88                unsigned int day:5;     /* Day (1-31) */
89                unsigned int month:4;   /* Month (1-12) */
90                unsigned int year:7;    /* Year (1980 + 0-127) */
91        } manufacture_date;
92        u16 mode, temp, v, i, avgi;     /* Register values */
93        u16 relchg, abschg, remcap, chgcap;     /* Register values */
94        u16 rte, ate, atf, chgi, chgv;  /* Register values */
95        u16 status, cyclect, descap, desv;      /* Register values */
96};
97
98static int smartbatt_attach_adapter(struct i2c_adapter *adapter);
99static int smartbatt_detect(struct i2c_adapter *adapter, int address,
100                       unsigned short flags, int kind);
101static void smartbatt_init_client(struct i2c_client *client);
102static int smartbatt_detach_client(struct i2c_client *client);
103
104static int smartbatt_read(struct i2c_client *client, u8 reg);
105#if 0
106static int smartbatt_write_value(struct i2c_client *client, u8 reg, u16 value);
107#endif
108static void smartbatt_temp(struct i2c_client *client, int operation,
109                      int ctl_name, int *nrels_mag, long *results);
110static void smartbatt_i(struct i2c_client *client, int operation,
111                      int ctl_name, int *nrels_mag, long *results);
112static void smartbatt_v(struct i2c_client *client, int operation,
113                      int ctl_name, int *nrels_mag, long *results);
114static void smartbatt_time(struct i2c_client *client, int operation,
115                      int ctl_name, int *nrels_mag, long *results);
116static void smartbatt_alarms(struct i2c_client *client, int operation,
117                      int ctl_name, int *nrels_mag, long *results);
118static void smartbatt_charge(struct i2c_client *client, int operation,
119                      int ctl_name, int *nrels_mag, long *results);
120static void smartbatt_status(struct i2c_client *client, int operation,
121                      int ctl_name, int *nrels_mag, long *results);
122static void smartbatt_error(struct i2c_client *client, int operation,
123                      int ctl_name, int *nrels_mag, long *results);
124static void smartbatt_update_client(struct i2c_client *client);
125
126
127/* This is the driver that will be inserted */
128static struct i2c_driver smartbatt_driver = {
129        .name           = "Smart Battery chip driver",
130        .id             = I2C_DRIVERID_SMARTBATT,
131        .flags          = I2C_DF_NOTIFY,
132        .attach_adapter = smartbatt_attach_adapter,
133        .detach_client  = smartbatt_detach_client,
134};
135
136
137/* -- SENSORS SYSCTL START -- */
138
139/* Status Register Bits */
140/* * * * * * Alarm Bits * * * * */ 
141#define SMARTBATT_OVER_CHARGED_ALARM 0x8000
142#define SMARTBATT_TERMINATE_CHARGE_ALARM 0x4000
143#define SMARTBATT_OVER_TEMP_ALARM 0x1000
144#define SMARTBATT_TERMINATE_DISCHARGE_ALARM 0x0800
145#define SMARTBATT_REMAINING_CAPACITY_ALARM  0x0200
146#define SMARTBATT_REMAINING_TIME_ALARM 0x0100
147/* * * * * * Status Bits * * * * */
148#define SMARTBATT_INITIALIZED 0x0080
149#define SMARTBATT_DISCHARGING 0x0040
150#define SMARTBATT_FULLY_CHARGED 0x0020
151#define SMARTBATT_FULLY_DISCHARGED 0x0010
152/* * * * * * Error Bits * * * * */ 
153#define SMARTBATT_OK 0x0000
154#define SMARTBATT_BUSY 0x0001
155#define SMARTBATT_RESERVED_COMMAND 0x0002
156#define SMARTBATT_UNSUPPORTED_COMMAND 0x0003
157#define SMARTBATT_ACCESS_DENIED 0x0004
158#define SMARTBATT_OVER_UNDERFLOW 0x0005
159#define SMARTBATT_BAD_SIZE 0x0006
160#define SMARTBATT_UNKNOWN_ERROR 0x0007
161
162#define SMARTBATT_ALARM (SMARTBATT_OVER_CHARGED_ALARM \
163                | SMARTBATT_TERMINATE_CHARGE_ALARM | SMARTBATT_OVER_TEMP_ALARM \
164                | SMARTBATT_TERMINATE_DISCHARGE_ALARM \
165                | SMARTBATT_REMAINING_CAPACITY_ALARM \
166                | SMARTBATT_REMAINING_TIME_ALARM)
167
168#define SMARTBATT_STATUS (SMARTBATT_INITIALIZED | SMARTBATT_DISCHARGING \
169                | SMARTBATT_FULLY_CHARGED | SMARTBATT_FULLY_DISCHARGED )
170
171#define SMARTBATT_ERROR (SMARTBATT_BUSY | SMARTBATT_RESERVED_COMMAND \
172                | SMARTBATT_UNSUPPORTED_COMMAND | SMARTBATT_ACCESS_DENIED \
173                | SMARTBATT_OVER_UNDERFLOW | SMARTBATT_BAD_SIZE\
174                | SMARTBATT_UNKNOWN_ERROR)
175
176
177#define SMARTBATT_SYSCTL_I 1001
178#define SMARTBATT_SYSCTL_V 1002
179#define SMARTBATT_SYSCTL_TEMP 1003
180#define SMARTBATT_SYSCTL_TIME 1004
181#define SMARTBATT_SYSCTL_ALARMS 1005
182#define SMARTBATT_SYSCTL_STATUS 1006
183#define SMARTBATT_SYSCTL_ERROR 1007
184#define SMARTBATT_SYSCTL_CHARGE 1008
185
186/* -- SENSORS SYSCTL END -- */
187
188/* These files are created for each detected SMARTBATT. This is just a template;
189   though at first sight, you might think we could use a statically
190   allocated list, we need some way to get back to the parent - which
191   is done through one of the 'extra' fields which are initialized
192   when a new copy is allocated. */
193static ctl_table smartbatt_dir_table_template[] = {
194        {SMARTBATT_SYSCTL_I, "i", NULL, 0, 0444, NULL, &i2c_proc_real,
195         &i2c_sysctl_real, NULL, &smartbatt_i},
196        {SMARTBATT_SYSCTL_V, "v", NULL, 0, 0444, NULL, &i2c_proc_real,
197         &i2c_sysctl_real, NULL, &smartbatt_v},
198        {SMARTBATT_SYSCTL_TEMP, "temp", NULL, 0, 0444, NULL, &i2c_proc_real,
199         &i2c_sysctl_real, NULL, &smartbatt_temp},
200        {SMARTBATT_SYSCTL_TIME, "time", NULL, 0, 0444, NULL, &i2c_proc_real,
201         &i2c_sysctl_real, NULL, &smartbatt_time},
202        {SMARTBATT_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
203         &i2c_sysctl_real, NULL, &smartbatt_alarms},
204        {SMARTBATT_SYSCTL_STATUS, "status", NULL, 0, 0444, NULL, &i2c_proc_real,
205         &i2c_sysctl_real, NULL, &smartbatt_status},
206        {SMARTBATT_SYSCTL_ERROR, "error", NULL, 0, 0444, NULL, &i2c_proc_real,
207         &i2c_sysctl_real, NULL, &smartbatt_error},
208        {SMARTBATT_SYSCTL_CHARGE, "charge", NULL, 0, 0444, NULL, &i2c_proc_real,
209         &i2c_sysctl_real, NULL, &smartbatt_charge},
210        {0}
211};
212
213static int smartbatt_id = 0;
214
215static int smartbatt_attach_adapter(struct i2c_adapter *adapter)
216{
217        return i2c_detect(adapter, &addr_data, smartbatt_detect);
218}
219
220/* This function is called by i2c_detect */
221int smartbatt_detect(struct i2c_adapter *adapter, int address,
222                unsigned short flags, int kind)
223{
224        int i;
225        struct i2c_client *new_client;
226        struct smartbatt_data *data;
227        int err = 0;
228        const char *type_name, *client_name;
229
230        /* Make sure we aren't probing the ISA bus!! This is just a safety check
231           at this moment; i2c_detect really won't call us. */
232#ifdef DEBUG
233        if (i2c_is_isa_adapter(adapter)) {
234                printk
235                    ("smartbatt.o: smartbatt_detect called for an ISA bus adapter?!?\n");
236                return 0;
237        }
238#endif
239
240        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
241                    goto ERROR0;
242
243        /* OK. For now, we presume we have a valid client. We now create the
244           client structure, even though we cannot fill it completely yet.
245           But it allows us to access smartbatt_{read,write}_value. */
246        if (!(data = kmalloc(sizeof(struct smartbatt_data), GFP_KERNEL))) {
247                err = -ENOMEM;
248                goto ERROR0;
249        }
250
251        new_client = &data->client;
252        new_client->addr = address;
253        new_client->data = data;
254        new_client->adapter = adapter;
255        new_client->driver = &smartbatt_driver;
256        new_client->flags = 0;
257
258        /* Lousy detection. Check the temp, voltage, and current registers */
259        if (kind < 0) {
260                for (i = 0x08; i <= 0x0a; i++)
261                        if (i2c_smbus_read_word_data(new_client, i) == 0xffff)
262                                goto ERROR1;
263        }
264
265        kind = smartbatt;
266        type_name = "smartbatt";
267        client_name = "Smart Battery";
268
269        /* Fill in the remaining client fields and put it into the global list */
270        strcpy(new_client->name, client_name);
271
272        new_client->id = smartbatt_id++;
273        data->valid = 0;
274        init_MUTEX(&data->update_lock);
275
276        /* Tell the I2C layer a new client has arrived */
277        if ((err = i2c_attach_client(new_client)))
278                goto ERROR3;
279
280        /* Register a new directory entry with module sensors */
281        if ((i = i2c_register_entry(new_client, type_name,
282                                        smartbatt_dir_table_template,
283                                        THIS_MODULE)) < 0) {
284                err = i;
285                goto ERROR4;
286        }
287        data->sysctl_id = i;
288
289        smartbatt_init_client(new_client);
290        return 0;
291
292/* OK, this is not exactly good programming practice, usually. But it is
293   very code-efficient in this case. */
294
295      ERROR4:
296        i2c_detach_client(new_client);
297      ERROR3:
298      ERROR1:
299        kfree(data);
300      ERROR0:
301        return err;
302}
303
304static int smartbatt_detach_client(struct i2c_client *client)
305{
306        int err;
307
308        i2c_deregister_entry(((struct smartbatt_data *) (client->data))->
309                                 sysctl_id);
310
311        if ((err = i2c_detach_client(client))) {
312                printk
313                    ("smartbatt.o: Client deregistration failed, client not detached.\n");
314                return err;
315        }
316
317        kfree(client->data);
318
319        return 0;
320}
321
322static int smartbatt_read(struct i2c_client *client, u8 reg)
323{ 
324        int n = COMM_TIMEOUT;
325        int val;
326        do { 
327                val = i2c_smbus_read_word_data(client, reg);
328        } while ((val == -1) && (n-- > 0));
329        return val;
330}
331
332#if 0
333static int smartbatt_write_value(struct i2c_client *client, u8 reg, u16 value)
334{
335        /* Why swap bytes? */
336        return i2c_smbus_write_word_data(client, reg, swab16(value));
337}
338#endif
339
340#define COMM_TIMEOUT 16
341static void get_battery_info(struct i2c_client *client)
342{
343  struct smartbatt_data *data = client->data;
344  int val;
345
346  down(&data->update_lock);
347  data->chgcap = smartbatt_read(client, SMARTBATT_REG_CHGCAP);
348  data->descap = smartbatt_read(client, SMARTBATT_REG_DESCAP);
349  data->desv = smartbatt_read(client, SMARTBATT_REG_DESV);
350  /* ManufactureDate */
351  val = smartbatt_read(client, SMARTBATT_REG_DATE);
352  data->manufacture_date.day=val & 0x1F;
353  data->manufacture_date.month=(val >> 5) & 0x0F;
354  data->manufacture_date.year=(val >> 9) & 0x7F;
355
356  /* SerialNumber */
357  data->serial = smartbatt_read(client, SMARTBATT_REG_SERIAL);
358#if 0
359  /* ManufacturerName */
360  n=COMM_TIMEOUT;
361  do {
362    val = i2c_smbus_read_block_data(client, 0x20, data->manufacturer);
363  } while ((val == -1) && (n-- > 0));
364  data->manufacturer[val]=0;   
365
366  /* DeviceName */
367  n=COMM_TIMEOUT;
368  do {
369    val = i2c_smbus_read_block_data(client, 0x21, data->device);
370  } while ((val == -1) && (n-- > 0));
371  data->device[val]=0; 
372
373  /* DeviceChemistry */
374  n=COMM_TIMEOUT;
375  do {
376    val = i2c_smbus_read_block_data(client, 0x22, data->chemistry);
377  } while ((val == -1) && (n-- > 0));
378  data->chemistry[val]=0;       
379#endif
380  up(&data->update_lock);
381
382}
383
384static void smartbatt_init_client(struct i2c_client *client)
385{
386        get_battery_info( client );
387}
388
389static void smartbatt_update_client(struct i2c_client *client)
390{
391        struct smartbatt_data *data = client->data;
392
393        down(&data->update_lock);
394
395        if ((jiffies - data->last_updated > HZ + HZ / 2) ||
396            (jiffies < data->last_updated) || !data->valid) {
397                data->mode = smartbatt_read(client, SMARTBATT_REG_MODE);
398                data->temp = smartbatt_read(client, SMARTBATT_REG_TEMP);
399                data->i = smartbatt_read(client, SMARTBATT_REG_I);
400                data->avgi = smartbatt_read(client, SMARTBATT_REG_AVGI);
401                data->v = smartbatt_read(client, SMARTBATT_REG_V);
402                data->chgi = smartbatt_read(client, SMARTBATT_REG_CHGI);
403                data->chgv = smartbatt_read(client, SMARTBATT_REG_CHGV);
404                data->ate = smartbatt_read(client, SMARTBATT_REG_AVGTIME_E);
405                data->atf = smartbatt_read(client, SMARTBATT_REG_AVGTIME_F);
406                data->rte = smartbatt_read(client, SMARTBATT_REG_RUNTIME_E);
407                data->status = smartbatt_read(client, SMARTBATT_REG_STATUS);
408                data->cyclect = smartbatt_read(client, SMARTBATT_REG_CYCLECT);
409                data->relchg = smartbatt_read(client, SMARTBATT_REG_RELCHG);
410                data->abschg = smartbatt_read(client, SMARTBATT_REG_ABSCHG);
411                data->remcap = smartbatt_read(client, SMARTBATT_REG_REMCAP);
412                data->last_updated = jiffies;
413                data->valid = 1;
414        }
415
416        up(&data->update_lock);
417}
418
419
420void smartbatt_temp(struct i2c_client *client, int operation, int ctl_name,
421               int *nrels_mag, long *results)
422{
423        struct smartbatt_data *data = client->data;
424        if (operation == SENSORS_PROC_REAL_INFO)
425                *nrels_mag = 1;
426        else if (operation == SENSORS_PROC_REAL_READ) {
427                smartbatt_update_client(client);
428                results[0] = data->temp - 2731; /* convert from Kelvin */
429                *nrels_mag = 1;
430        }
431}
432
433void smartbatt_i(struct i2c_client *client, int operation, int ctl_name,
434               int *nrels_mag, long *results)
435{
436        struct smartbatt_data *data = client->data;
437        if (operation == SENSORS_PROC_REAL_INFO)
438                *nrels_mag = 3;
439        else if (operation == SENSORS_PROC_REAL_READ) {
440                smartbatt_update_client(client);
441                results[0] = data->chgi;
442                results[1] = data->avgi;
443                results[2] = data->i;
444                *nrels_mag = 3;
445        }
446}
447
448void smartbatt_v(struct i2c_client *client, int operation, int ctl_name,
449               int *nrels_mag, long *results)
450{
451        struct smartbatt_data *data = client->data;
452        if (operation == SENSORS_PROC_REAL_INFO)
453                *nrels_mag = 3;
454        else if (operation == SENSORS_PROC_REAL_READ) {
455                smartbatt_update_client(client);
456                results[0] = data->chgv;
457                results[1] = data->v;
458                *nrels_mag = 2;
459        }
460}
461
462void smartbatt_time(struct i2c_client *client, int operation, int ctl_name,
463               int *nrels_mag, long *results)
464{
465        struct smartbatt_data *data = client->data;
466        if (operation == SENSORS_PROC_REAL_INFO)
467                *nrels_mag = 0;
468        else if (operation == SENSORS_PROC_REAL_READ) {
469                smartbatt_update_client(client);
470                results[0] = data->ate;
471                results[1] = data->atf;
472                results[2] = data->rte;
473                *nrels_mag = 3;
474        }
475}
476
477void smartbatt_alarms(struct i2c_client *client, int operation, int ctl_name,
478                 int *nrels_mag, long *results)
479{
480        struct smartbatt_data *data = client->data;
481        if (operation == SENSORS_PROC_REAL_INFO)
482                *nrels_mag = 0;
483        else if (operation == SENSORS_PROC_REAL_READ) {
484                smartbatt_update_client(client);
485                results[0] = data->status & SMARTBATT_ALARM;
486                *nrels_mag = 1;
487        }
488}
489
490void smartbatt_status(struct i2c_client *client, int operation, int ctl_name,
491                 int *nrels_mag, long *results)
492{
493        struct smartbatt_data *data = client->data;
494        if (operation == SENSORS_PROC_REAL_INFO)
495                *nrels_mag = 0;
496        else if (operation == SENSORS_PROC_REAL_READ) {
497                smartbatt_update_client(client);
498                results[0] = data->status & SMARTBATT_STATUS;
499                *nrels_mag = 1;
500        }
501}
502
503void smartbatt_error(struct i2c_client *client, int operation, int ctl_name,
504                 int *nrels_mag, long *results)
505{
506        struct smartbatt_data *data = client->data;
507        if (operation == SENSORS_PROC_REAL_INFO)
508                *nrels_mag = 0;
509        else if (operation == SENSORS_PROC_REAL_READ) {
510                smartbatt_update_client(client);
511                results[0] = data->status & SMARTBATT_ERROR;
512                *nrels_mag = 1;
513        }
514}
515
516void smartbatt_charge(struct i2c_client *client, int operation, int ctl_name,
517                 int *nrels_mag, long *results)
518{
519        struct smartbatt_data *data = client->data;
520        if (operation == SENSORS_PROC_REAL_INFO)
521                *nrels_mag = 0;
522        else if (operation == SENSORS_PROC_REAL_READ) {
523                smartbatt_update_client(client);
524                results[0] = data->relchg;
525                results[1] = data->abschg;
526                results[2] = data->chgi;
527                results[3] = data->chgv;
528                *nrels_mag = 4;
529        }
530}
531
532static int __init sm_smartbatt_init(void)
533{
534        printk("smartbatt.o version %s (%s)\n", LM_VERSION, LM_DATE);
535        return i2c_add_driver(&smartbatt_driver);
536}
537
538static void __exit sm_smartbatt_exit(void)
539{
540        i2c_del_driver(&smartbatt_driver);
541}
542
543
544
545MODULE_AUTHOR("M. Studebaker <mdsxyz123@yahoo.com>");
546MODULE_DESCRIPTION("Smart Battery driver");
547MODULE_LICENSE("GPL");
548
549module_init(sm_smartbatt_init);
550module_exit(sm_smartbatt_exit);
Note: See TracBrowser for help on using the browser.